{"record":{"id":"6c644c18b6c17f75","repo":"calcom/cal.diy","slug":"bad-request-invalid-json","errorCode":null,"errorMessage":"Bad Request (Invalid JSON)","messagePattern":"Bad Request \\(Invalid JSON\\)","errorType":"http","errorClass":"HttpError","httpStatus":400,"severity":"warning","filePath":"apps/web/app/api/parseRequestData.ts","lineNumber":37,"sourceCode":"\nexport async function parseMultiFormData(req: NextRequest): Promise<Record<string, any>> {\n  try {\n    const formData = await req.formData();\n    return Object.fromEntries(formData.entries());\n  } catch (e) {\n    log.error(`Invalid Multi Form Data: ${e} from path ${req.nextUrl}`);\n    throw new HttpError({ statusCode: 400, message: \"Bad Request (Invalid Multi Form Data)\" });\n  }\n}\n\nexport async function parseRequestData(req: NextRequest): Promise<Record<string, any>> {\n  const contentType = req.headers.get(\"content-type\") ?? \"application/json\";\n  if (contentType.includes(\"application/json\")) {\n    try {\n      return await req.json();\n    } catch (e) {\n      log.error(`Invalid JSON: ${e} from path ${req.nextUrl}`);\n      throw new HttpError({ statusCode: 400, message: \"Bad Request (Invalid JSON)\" });\n    }\n  }\n\n  if (contentType.includes(\"application/x-www-form-urlencoded\")) {\n    return await parseUrlFormData(req);\n  }\n\n  if (contentType.includes(\"multipart/form-data\")) {\n    return await parseMultiFormData(req);\n  }\n\n  log.error(`Unsupported content type: ${contentType} from path ${req.nextUrl}`);\n  throw new HttpError({ statusCode: 415, message: `Unsupported Content-Type. Expected ${contentType}` });\n}\n","sourceCodeStart":19,"sourceCodeEnd":52,"githubUrl":"https://github.com/calcom/cal.diy/blob/176037d0afbe572f870a3c702985e7cd83fe6c0c/apps/web/app/api/parseRequestData.ts#L19-L52","documentation":"Thrown by parseRequestData (HttpError, HTTP 400) when req.json() throws for an application/json request — the body is not valid JSON. A log.error records the parse exception and path. This is the JSON branch of the content-type dispatcher.","triggerScenarios":"POST with Content-Type application/json whose body is malformed JSON: trailing commas, single quotes, unquoted keys, truncated payload, or HTML/text returned through a proxy that rewrites content-type.","commonSituations":"Hand-built fetch with a non-JSON string body, JSON.stringify omitted, body cut off by a size limit, double JSON encoding, BOM/control characters in the payload.","solutions":["Always JSON.stringify objects before sending as application/json.","Validate JSON.parse in a try/catch on the client before submit to surface the exact syntax error.","Ensure proxies/middleware do not alter or truncate the body, and that Content-Type matches the actual payload.","Inspect the logged underlying error for the JSON parse position."],"exampleFix":"// before\nawait fetch('/api/x', {\n  method: 'POST',\n  headers: { 'Content-Type': 'application/json' },\n  body: '{ name: \"a\", }', // invalid JSON\n});\n\n// after\nconst payload = JSON.stringify({ name: 'a' });\nJSON.parse(payload); // sanity check client-side\nawait fetch('/api/x', {\n  method: 'POST',\n  headers: { 'Content-Type': 'application/json' },\n  body: payload,\n});","handlingStrategy":"try-catch","validationCode":"// Validate JSON client-side before sending\nconst body = JSON.stringify(payload);\nJSON.parse(body); // throws here if payload is not serializable cleanly\nawait fetch('/api/x', {\n  method: 'POST',\n  headers: { 'Content-Type': 'application/json' },\n  body,\n});","typeGuard":"function isParsableJson(s: string): boolean {\n  try { JSON.parse(s); return true; } catch { return false; }\n}","tryCatchPattern":"try {\n  return await req.json();\n} catch (e) {\n  throw new HttpError({ statusCode: 400, message: 'Bad Request (Invalid JSON)' });\n}","preventionTips":["Always JSON.stringify objects for application/json requests.","Set Content-Type to match the actual payload shape.","Ensure proxies do not truncate or rewrite the body."],"tags":["request-parsing","json","validation","content-type"],"backgroundTag":null,"analyzedSha":"176037d0afbe572f870a3c702985e7cd83fe6c0c","analyzedAt":"2026-08-12T19:12:41.464Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}