payloadcms/payload · error · APIError
Invalid JSON
Error message
Invalid JSON
What it means
Thrown during request body parsing when the `Content-Type` is `application/json` but `JSON.parse` raises a `SyntaxError`. Payload reads the raw body text and parses it before hooks run, so malformed JSON never reaches your field-level logic.
Source
Thrown at packages/payload/src/utilities/addDataAndFileToRequest.ts:30
*/
export const addDataAndFileToRequest: AddDataAndFileToRequest = async (req) => {
const { body, headers, method, payload } = req
if (method && ['PATCH', 'POST', 'PUT'].includes(method.toUpperCase()) && body) {
const [contentType] = (headers.get('Content-Type') || '').split(';', 1)
const bodyByteSize = parseInt(req.headers.get('Content-Length') || '0', 10)
const hasBodyStream = req.body !== null
if (contentType === 'application/json') {
try {
const text = await req.text?.()
const data = text ? JSON.parse(text) : {}
req.data = data
// @ts-expect-error attach json method to request
req.json = () => Promise.resolve(data)
} catch (error) {
if (error instanceof SyntaxError) {
throw new APIError('Invalid JSON', 400)
}
req.payload.logger.error(error)
throw error
}
} else if ((bodyByteSize || hasBodyStream) && contentType?.includes('multipart/')) {
const { error, fields, files } = await processMultipartFormdata({
options: {
...(payload.config.bodyParser || {}),
...(payload.config.upload || {}),
},
request: req as Request,
})
if (error) {
throw new APIError(error.message)
}
// Set all files on req.files for access by hooksView on GitHub (pinned to 00c58b35c0)
Solutions
- Ensure the client sends strict JSON: double-quoted keys, no trailing commas, no comments.
- Use `JSON.stringify(obj)` (JS) or the language canonical JSON serializer -- do not send object literals.
- Verify the full body reaches the server (check `Content-Length`, proxy buffering, no truncation).
- Test the body with a JSON linter before sending.
Example fix
// before
await fetch('/api/users', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: { name: 'Jane' }, // raw object -- sent as '[object Object]'
})
// after
await fetch('/api/users', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name: 'Jane' }),
}) Defensive patterns
Strategy: validation
Validate before calling
// Validate JSON before sending
function safeJsonStringify(obj) {
return JSON.stringify(obj)
}
const body = safeJsonStringify(payload)
JSON.parse(body) // round-trip check
await fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body }) Try / catch
try {
await fetch(url, { method: 'POST', body: JSON.stringify(data), headers: jsonHeaders })
} catch (e) {
if (e instanceof APIError && e.message === 'Invalid JSON') {
// log the raw body and fix the serialization
} else throw e
} Prevention
- Always use JSON.stringify for the body -- never pass raw objects.
- Validate JSON round-trips before sending (parse what you stringify).
- Avoid trailing commas, comments, and single-quoted strings in payloads.
- Set Content-Type: application/json on every JSON request.
When it happens
Trigger: Any POST/PATCH/PUT request with `Content-Type: application/json` whose body is not valid JSON: trailing commas, unquoted keys, single-quoted strings, truncated payload, or BOM-prefixed content.
Common situations: Client sends a JS object literal (not strict JSON) e.g. `{ key: "value" }` or `{a: 1,}`; a proxy truncated the body; `fetch` was called with `body: obj` instead of `body: JSON.stringify(obj)`; hand-crafted curl with unbalanced braces.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- ${value} is not allowed as a JSON query value
- ${value} is not allowed as a JSON query value
- JSONObject cannot represent non-object value: ${value}
- JSONObject cannot represent non-object value: ${print(ast)}
- Network response was not ok
AI-assisted analysis of payloadcms/payload@00c58b35c0 (2026-08-12).
Data as JSON: /api/errors/6a9907b0285db110.
Report an issue: GitHub.