{"record":{"id":"6a9907b0285db110","repo":"payloadcms/payload","slug":"invalid-json","errorCode":null,"errorMessage":"Invalid JSON","messagePattern":"Invalid JSON","errorType":"exception","errorClass":"APIError","httpStatus":400,"severity":"error","filePath":"packages/payload/src/utilities/addDataAndFileToRequest.ts","lineNumber":30,"sourceCode":" */\nexport const addDataAndFileToRequest: AddDataAndFileToRequest = async (req) => {\n  const { body, headers, method, payload } = req\n\n  if (method && ['PATCH', 'POST', 'PUT'].includes(method.toUpperCase()) && body) {\n    const [contentType] = (headers.get('Content-Type') || '').split(';', 1)\n    const bodyByteSize = parseInt(req.headers.get('Content-Length') || '0', 10)\n    const hasBodyStream = req.body !== null\n\n    if (contentType === 'application/json') {\n      try {\n        const text = await req.text?.()\n        const data = text ? JSON.parse(text) : {}\n        req.data = data\n        // @ts-expect-error attach json method to request\n        req.json = () => Promise.resolve(data)\n      } catch (error) {\n        if (error instanceof SyntaxError) {\n          throw new APIError('Invalid JSON', 400)\n        }\n        req.payload.logger.error(error)\n        throw error\n      }\n    } else if ((bodyByteSize || hasBodyStream) && contentType?.includes('multipart/')) {\n      const { error, fields, files } = await processMultipartFormdata({\n        options: {\n          ...(payload.config.bodyParser || {}),\n          ...(payload.config.upload || {}),\n        },\n        request: req as Request,\n      })\n\n      if (error) {\n        throw new APIError(error.message)\n      }\n\n      // Set all files on req.files for access by hooks","sourceCodeStart":12,"sourceCodeEnd":48,"githubUrl":"https://github.com/payloadcms/payload/blob/00c58b35c0ed348ddc22daabf467b139727214fd/packages/payload/src/utilities/addDataAndFileToRequest.ts#L12-L48","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nawait fetch('/api/users', {\n  method: 'POST',\n  headers: { 'Content-Type': 'application/json' },\n  body: { name: 'Jane' }, // raw object -- sent as '[object Object]'\n})\n\n// after\nawait fetch('/api/users', {\n  method: 'POST',\n  headers: { 'Content-Type': 'application/json' },\n  body: JSON.stringify({ name: 'Jane' }),\n})","handlingStrategy":"validation","validationCode":"// Validate JSON before sending\nfunction safeJsonStringify(obj) {\n  return JSON.stringify(obj)\n}\nconst body = safeJsonStringify(payload)\nJSON.parse(body) // round-trip check\nawait fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body })","typeGuard":null,"tryCatchPattern":"try {\n  await fetch(url, { method: 'POST', body: JSON.stringify(data), headers: jsonHeaders })\n} catch (e) {\n  if (e instanceof APIError && e.message === 'Invalid JSON') {\n    // log the raw body and fix the serialization\n  } else throw e\n}","preventionTips":["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."],"tags":["json","body-parsing","validation","request"],"backgroundTag":null,"analyzedSha":"00c58b35c0ed348ddc22daabf467b139727214fd","analyzedAt":"2026-08-12T20:45:03.758Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}