Skip to content

invalid uuid check is returning a plain object instead of sending HTTP response#2734

Open
adityamane765 wants to merge 3 commits into
DefiLlama:masterfrom
adityamane765:fix/config-invalid-uuid-response-2
Open

invalid uuid check is returning a plain object instead of sending HTTP response#2734
adityamane765 wants to merge 3 commits into
DefiLlama:masterfrom
adityamane765:fix/config-invalid-uuid-response-2

Conversation

@adityamane765

@adityamane765 adityamane765 commented Jun 13, 2026

Copy link
Copy Markdown
Contributor

in getConfigPool the invalid uuid early return was doing return { status: 'invalid uuid parameter' } which is just a plain JS object from the async function so express alw ignores this and no HTTP response is ever sent, and the client connection hangs until timeout
fixed by calling res.status(400).json(...) instead

Summary by CodeRabbit

  • Bug Fixes
    • Invalid configuration identifiers now immediately return an HTTP 400 JSON response with a clear error message.
    • Configuration-related errors are now propagated to the centralized JSON error handler, ensuring consistent HTTP status codes and JSON {status, message} responses across failures.

@coderabbitai

coderabbitai Bot commented Jun 13, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Controllers in src/api/controllers/config.js now send HTTP 400 JSON for invalid UUID parameters in getConfigPool, and getDistinctID/getConfigPool/getAllPools throw AppError('Couldn't get data', 404) when DB queries return no data; app errorHandler now returns JSON using err.statusCode.

Changes

Config controller error handling

Layer / File(s) Summary
UUID validation returns HTTP 400
src/api/controllers/config.js
getConfigPool now responds with res.status(400).json({ status: 'invalid uuid parameter' }) when the configID URL parameter is not a valid UUID.
Throw AppError on no DB response + JSON errorHandler
src/api/controllers/config.js, src/api/app.js
getDistinctID, getConfigPool, and getAllPools now throw new AppError('Couldn't get data', 404) when their DB queries yield no data instead of returning an AppError value. errorHandler now maps err.statusCode (fallback 500) and returns JSON { status: err.status ?? 'error', message: err.message }.

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant getConfigPool
  participant getDistinctID
  participant getAllPools
  participant Database
  participant errorHandler

  Client->>getConfigPool: HTTP request (configID)
  getConfigPool->>Database: query by configID
  Database-->>getConfigPool: null / no data
  getConfigPool->>errorHandler: throw AppError('Couldn't get data',404)

  Client->>getDistinctID: HTTP request
  getDistinctID->>Database: distinct ID query
  Database-->>getDistinctID: null
  getDistinctID->>errorHandler: throw AppError('Couldn't get data',404)

  Client->>getAllPools: HTTP request
  getAllPools->>Database: query all pools
  Database-->>getAllPools: null
  getAllPools->>errorHandler: throw AppError('Couldn't get data',404)

  errorHandler->>Client: HTTP response (res.status(err.statusCode||500).json({status: err.status ?? 'error', message: err.message}))
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰
I dug through configs, sniffed each root,
Bad UUIDs now get a spicy 400 boot.
Silent returns are chased away—
Errors thrown bright to middleware's day.
Hooray for clearer server routes!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly addresses the main issue fixed in the PR: changing the invalid UUID check in getConfigPool to send an HTTP JSON response instead of returning a plain object.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/api/controllers/config.js (1)

30-32: ⚠️ Potential issue | 🔴 Critical | 🏗️ Heavy lift

Potential error handling issue - same pattern as the bug fixed on line 44. The code returns new AppError(...) without throwing it or passing it to Express error middleware. If no error middleware automatically catches AppError instances, these responses will hang.

  • src/api/controllers/config.js#L30-L32: In getDistinctID, change to throw new AppError(...) or send response directly with res.status(404).json(...)
  • src/api/controllers/config.js#L56-L58: In getConfigPool, change to throw new AppError(...) or send response directly with res.status(404).json(...)
  • src/api/controllers/config.js#L81-L83: In getAllPools, change to throw new AppError(...) or send response directly with res.status(404).json(...)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/api/controllers/config.js` around lines 30 - 32, In
src/api/controllers/config.js (lines 30-32, 56-58, 81-83) the handlers
getDistinctID, getConfigPool, and getAllPools currently return new AppError(...)
which does not propagate; change each site to throw new AppError(...) instead
(so the central Express error middleware handles it) — specifically replace the
return new AppError(...) in getDistinctID (30-32), getConfigPool (56-58) and
getAllPools (81-83) with throw new AppError(...) (alternatively you may send an
immediate response with res.status(404).json(...) if you prefer per-handler
responses, but keep behavior consistent across these three functions).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@src/api/controllers/config.js`:
- Around line 30-32: In src/api/controllers/config.js (lines 30-32, 56-58,
81-83) the handlers getDistinctID, getConfigPool, and getAllPools currently
return new AppError(...) which does not propagate; change each site to throw new
AppError(...) instead (so the central Express error middleware handles it) —
specifically replace the return new AppError(...) in getDistinctID (30-32),
getConfigPool (56-58) and getAllPools (81-83) with throw new AppError(...)
(alternatively you may send an immediate response with res.status(404).json(...)
if you prefer per-handler responses, but keep behavior consistent across these
three functions).

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 26ef6027-93a2-415f-b414-aa411baf3f8f

📥 Commits

Reviewing files that changed from the base of the PR and between 7121256 and 27799e6.

📒 Files selected for processing (1)
  • src/api/controllers/config.js

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/api/controllers/config.js`:
- Around line 30-32: The controllers throw AppError but the centralized
errorHandler always returns 500+HTML, so fix the controllers to respond with
proper 404 JSON at the three sites rather than relying on AppError: in
src/api/controllers/config.js (lines 30-32) inside getDistinctID replace the
throw with an immediate HTTP response like res.status(404).json({ error:
"Couldn't get data" }) (or equivalent JSON shape used elsewhere); in
src/api/controllers/config.js (lines 56-58) inside getConfigPool do the same
replacement with res.status(404).json({...}); and in
src/api/controllers/config.js (lines 81-83) inside getAllPools also replace the
throw with res.status(404).json({...}). Alternatively, if you prefer a single
centralized fix, update the errorHandler to honor AppError.statusCode and return
JSON (but do not do both); choose one approach and apply consistently to these
three sites.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b39bd5c3-f0eb-4efa-b9c3-7a4b037e57ac

📥 Commits

Reviewing files that changed from the base of the PR and between 27799e6 and 3b23184.

📒 Files selected for processing (1)
  • src/api/controllers/config.js

Comment thread src/api/controllers/config.js

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/api/app.js`:
- Around line 57-58: The error handler currently returns err.message for all
responses which can leak internals for 5xx errors; change the response so that
after computing const statusCode = err.statusCode ?? 500 you use a conditional
message (e.g., const message = statusCode >= 500 ? 'Internal server error' :
err.message) and then call res.status(statusCode).json({ status: err.status ??
'error', message }); keep the existing status field behavior and only substitute
a generic message for server errors.
- Around line 55-59: The global Express error middleware function errorHandler
currently unconditionally writes a JSON response and can cause
ERR_HTTP_HEADERS_SENT if a response has already begun; add an early guard in
errorHandler that checks if res.headersSent and if so calls return next(err) to
delegate to the default/next error handler, otherwise continue to compute
statusCode and send the JSON response as before.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a5448e12-a461-4a50-a2b6-e9e85728a33e

📥 Commits

Reviewing files that changed from the base of the PR and between 3b23184 and 9abfffd.

📒 Files selected for processing (1)
  • src/api/app.js

Comment thread src/api/app.js
Comment on lines 55 to 59
function errorHandler (err, req, res, next) {
console.log(err)
res.status(500)
res.render('error', { error: err })
const statusCode = err.statusCode ?? 500
res.status(statusCode).json({ status: err.status ?? 'error', message: err.message })
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify whether error middleware already guards headersSent
rg -n -C3 'function errorHandler|headersSent|res\.status\(statusCode\)\.json' src/api/app.js

# Inspect error producers that can reach middleware
rg -n -C2 'throw new AppError|next\(err\)|Promise\.reject|throw ' src/api/controllers src/api/routes src/api

Repository: DefiLlama/yield-server

Length of output: 2117


🏁 Script executed:

#!/bin/bash
rg -n "class AppError|function AppError|statusCode|fail" src/api src/utils src -S
echo "----"
rg -n "res\.status\(400\)\.json|invalid uuid|UUID|uuid|Bad Request" src/api/controllers -S

Repository: DefiLlama/yield-server

Length of output: 50379


🏁 Script executed:

#!/bin/bash
rg -n "class AppError|function AppError|statusCode|fail|status\s*=" src/api src/utils src -S
echo "----"
rg -n "res\.status\(400\)\.json|invalid uuid|UUID|uuid|Bad Request" src/api/controllers -S

Repository: DefiLlama/yield-server

Length of output: 50379


Add a res.headersSent guard to the global Express error middleware

src/api/app.js’s errorHandler always calls res.status(...).json(...) without checking res.headersSent, so if a response has already started, Express can throw ERR_HTTP_HEADERS_SENT instead of delegating. Add an early if (res.headersSent) return next(err).

Suggested fix
 function errorHandler (err, req, res, next) {
   console.log(err)
+  if (res.headersSent) {
+    return next(err)
+  }
   const statusCode = err.statusCode ?? 500
   res.status(statusCode).json({ status: err.status ?? 'error', message: err.message })
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/api/app.js` around lines 55 - 59, The global Express error middleware
function errorHandler currently unconditionally writes a JSON response and can
cause ERR_HTTP_HEADERS_SENT if a response has already begun; add an early guard
in errorHandler that checks if res.headersSent and if so calls return next(err)
to delegate to the default/next error handler, otherwise continue to compute
statusCode and send the JSON response as before.

Comment thread src/api/app.js
Comment on lines +57 to +58
const statusCode = err.statusCode ?? 500
res.status(statusCode).json({ status: err.status ?? 'error', message: err.message })

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Avoid returning raw internal error messages for 5xx responses.

At Line 58, message: err.message will expose internal failure details on unexpected server errors. Prefer a generic message for statusCode >= 500, while keeping specific messages for 4xx AppError flows.

Suggested fix
 function errorHandler (err, req, res, next) {
   console.log(err)
   const statusCode = err.statusCode ?? 500
-  res.status(statusCode).json({ status: err.status ?? 'error', message: err.message })
+  const message = statusCode >= 500 ? 'Internal server error' : err.message
+  res.status(statusCode).json({ status: err.status ?? 'error', message })
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/api/app.js` around lines 57 - 58, The error handler currently returns
err.message for all responses which can leak internals for 5xx errors; change
the response so that after computing const statusCode = err.statusCode ?? 500
you use a conditional message (e.g., const message = statusCode >= 500 ?
'Internal server error' : err.message) and then call
res.status(statusCode).json({ status: err.status ?? 'error', message }); keep
the existing status field behavior and only substitute a generic message for
server errors.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant