DEV Community

Jeff
Jeff

Posted on Originally published at powerduck.com

Debugging a 400 Caused by a Trailing Comma in JSON

Quick answer: If the server returns 400 on a body that looks like valid JSON, check for a trailing comma after the last object member or array element. JSON does not allow it, while JavaScript literals do, so the eye accepts what the parser rejects. Validate the raw body with a strict parser, remove the comma, and serialize the body instead of typing it.

Why one comma becomes a 400

JSON is a strict format. The grammar expects a comma between members, not after the last one, so {"a": 1,} and [1, 2,] fail at parse time. The server cannot bind the body to an object and answers 400 before any business logic runs.

The confusing part is that the same text is legal as a JavaScript object or array literal, where a dangling comma has been allowed for years. A payload copied from code or written in a JavaScript style can look correct on screen and still be unparseable as JSON, and the error often names an unexpected token such as } or ] just past the comma.

Where the comma usually enters

Hand-written bodies are the most common source, especially when a last field is deleted and the comma before it is left behind. Pasting from code or generated edits written in JavaScript syntax carries the same risk when the text is sent as JSON without a serialization step.

The failure is invisible until the bytes leave the client. A unit test that builds the object in code never sees the malformed string, because the object in memory is fine; only the wire text is not.

How to locate it fast

Do not debug from the pretty-printed view alone. Capture the exact raw body and feed it to a strict parser such as JSON.parse; the reported byte offset takes you straight to the comma. Confirm the body is labeled application/json, since the wrong type produces a different error.

Once the comma is found, delete it and re-run the same request rather than editing several things at once. For a durable fix, build a native object and serialize it, so the formatter emits valid JSON by construction, and add a parse check that catches malformed bodies before they reach a shared environment.

Symptoms, causes, and fixes

Symptom Likely cause Fix
400 with an unexpected token } or ] Trailing comma after the last member Delete the comma
Body looks fine in the editor Highlighter treats it as JavaScript Validate the raw string as JSON
Fails only after a field is removed Comma left before the deleted member Re-serialize instead of manual edits
Passes unit tests but fails on the wire In-memory object is valid, text is not Add a parse check on the serialized body
Error offset sits near the end of the body Dangling comma in the last field Jump to the reported byte and inspect

Verify with a real request

After the fix, send the real request and assert on the status so the body is accepted, not merely looking corrected. A scenario can run the call as an ordered step, assert the 200 response, and keep the evidence. For offline work, a local mock can return 400 for the malformed body and 200 for the valid one while recording requests, so you confirm the client serializes correctly without touching the live service.

The mock models your client behavior, not the real server's parser, so the final step is still a live request. Powerduck sends these requests through the local main process without browser CORS limits, runs status and field assertions at each step, and can record mock traffic while you tighten serialization. For more, see the API debugging guide hub.

Honest limits

A green scenario proves that one body now parses; it does not prove every caller serializes correctly, and a mock returning scripted 400s cannot reproduce every real server's wording. Keep the live check as the source of truth, and if a verification script is missing, mark that step unverified rather than passed.

Frequently asked questions

Why does the same text work in JavaScript? JavaScript literals permit trailing commas; the JSON grammar does not, so the stricter parser applies once the text is sent as JSON.

Will the server tell me where the error is? Many parsers return an offset or token, but wording varies. Running your own strict parser on the raw body is the fastest way to locate it.

How do I stop this from recurring? Serialize bodies, add a parse or lint check before send, and keep a scenario that asserts the real request returns 200.

The bottom line

A 400 from a trailing comma is a format error, not a logic bug: the payload reads as JavaScript but fails as JSON. Validate the raw body with a strict parser to find the comma, and switch to serializing objects so the malformed text cannot be produced. Prove the result with a recorded scenario and a live request, and this class of 400 stops coming back.

Top comments (0)