Vulnerabilities
Verbose API Errors vs Generic Client Messages
April 25, 2026
Verbose API errors vs generic client messages is a production-logging split. Clients should get a short, stable code and a human sentence that does not name files, SQL, or framework versions. Operators should get the stack in logs you control. Chatty 500 bodies are reconnaissance. RoastMyOpsec's app-mode check does a soft GET to common API paths and looks for stack-trace or path-leak heuristics in small body snippets. It does not fuzz parameters or dump databases.
The practical difference
A generic message is 'Something went wrong' plus a request id. A verbose message is a Spring/Django/Node stack, a SQLSTATE, or /var/www/app/src/db.ts:214. The second one teaches strangers how to aim.
Debug mode in a framework is the usual source. Staging can be loud. Production should not copy that flag.
How to choose what the client sees
Map exception classes to public codes (validation, auth, not found, conflict, unavailable). Log the rest with the request id. Never send the exception message string to the browser if it was built from a driver error.
| Audience | Contents | Where | Takeaway |
|---|---|---|---|
| End user / SPA | Stable code, short copy, request id | JSON body | Boring is correct |
| On-call engineer | Stack, SQL, headers (redacted) | Server logs / APM | This is where the novel belongs |
| Attacker reading /api | Whatever you accidentally shipped | Same JSON they fetched | Do not donate paths and versions |
| Support ticket | Request id only | User paste | Lets you find the log line |
When a 200 with an error object is still a miss
Some APIs return HTTP 200 with { error: <driver text> }. Status codes are not the only leak. GraphQL errors arrays can name fields and internal types even when introspection is off.
Pair generic bodies with the GraphQL and CORS guides: one chatty surface is enough to map the rest.
Common mistakes
The first mistake is NODE_ENV=development in production 'just for this hotfix.'
The second mistake is returning err.message from a catch-all.
The third mistake is detailed errors on /api and generic ones on /.
Free audit the URL you own
RoastMyOpsec is a defensive public-surface roast: headers, cookies, sensitive paths, and more — no exploit payloads. Start with the free audit, then open the vault if the blurred findings look expensive.
Free audit nowFAQ
- Are stack traces in API JSON a CVE?
- Usually information disclosure, not remote code execution. They still speed up every other bug. Remove them from production responses.
- Can I keep detailed errors behind an admin header?
- A debug header that anyone can send is not a control. Prefer environment config and authenticated operator tools.
- How does RoastMyOpsec detect chatty errors?
- A bounded GET to common API paths and a heuristic on small body snippets. No fuzzing, no exploit payloads.
Sources
Related guides
Vulnerabilities
phpinfo() vs Verbose API Errors on ProductionVulnerabilities
Framework Debug Mode vs Verbose API ErrorsNews
Server Banners vs Stack Fingerprinting