{"record":{"id":"4e2cc613710fbe20","repo":"honojs/hono","slug":"malformed-json-in-request-body","errorCode":null,"errorMessage":"Malformed JSON in request body","messagePattern":"Malformed JSON in request body","errorType":"http","errorClass":"HTTPException","httpStatus":400,"severity":"warning","filePath":"src/validator/validator.ts","lineNumber":102,"sourceCode":"  E extends Env = any,\n>(\n  target: U,\n  validationFunc: VF\n): MiddlewareHandler<E, P, V, ExtractValidationResponse<VF>> => {\n  return async (c, next) => {\n    let value = {}\n    const contentType = c.req.header('Content-Type')\n\n    switch (target) {\n      case 'json':\n        if (!contentType || !jsonRegex.test(contentType)) {\n          break\n        }\n        try {\n          value = await c.req.json()\n        } catch {\n          const message = 'Malformed JSON in request body'\n          throw new HTTPException(400, { message })\n        }\n        break\n      case 'form': {\n        if (\n          !contentType ||\n          !(multipartRegex.test(contentType) || urlencodedRegex.test(contentType))\n        ) {\n          break\n        }\n\n        let formData: FormData\n\n        if (c.req.bodyCache.formData) {\n          formData = await c.req.bodyCache.formData\n        } else {\n          try {\n            const arrayBuffer = await c.req.arrayBuffer()\n            formData = await bufferToFormData(arrayBuffer, contentType)","sourceCodeStart":84,"sourceCodeEnd":120,"githubUrl":"https://github.com/honojs/hono/blob/e2740d5a1bd0b4254e517e3af8b60789284bc7bd/src/validator/validator.ts#L84-L120","documentation":"The validator middleware with type 'json' calls c.req.json(), which throws when the request body is not valid JSON. The middleware converts that into an HTTPException with status 400 and the message 'Malformed JSON in request body'.","triggerScenarios":"A request with Content-Type: application/json (or no type match for form) whose body is invalid JSON — trailing commas, single quotes, unquoted keys, HTML error pages, empty body, or form data sent with a JSON content type.","commonSituations":"Frontend sending FormData or urlencoded data while route validates as 'json'; client concatenating JSON fragments; proxies returning HTML error pages; missing body on POST; BOM or text/plain payloads parsed as JSON.","solutions":["Reproduce with curl sending the exact body and validate it with a JSON linter","Ensure the client sets body to JSON.stringify(obj) with Content-Type: application/json","If the client sends form data, switch the route validator to type 'form' or 'multipart'","Return a clearer 400 handler via app.onError for HTTPException to expose parse details in dev"],"exampleFix":"// before (client)\nfetch(url, { body: formData }) // route expects json\n// after\nfetch(url, { headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(obj) })","handlingStrategy":"validation","validationCode":"// client-side: ensure valid JSON before sending\nconst body = JSON.stringify(obj)\nawait fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body })","typeGuard":"const isJsonParseable = (s: string): boolean => { try { JSON.parse(s); return true } catch { return false } }","tryCatchPattern":"app.onError((err, c) => { if (err instanceof HTTPException && err.status === 400) return c.json({ error: 'bad request', message: err.message }, 400) throw err })","preventionTips":["Always pair JSON.stringify with the application/json content type","Match validator type ('json' vs 'form') to what the client actually sends","Reject empty bodies early in middleware","Return actionable 400 messages to clients"],"tags":["validation","json","request-body","http-400"],"backgroundTag":"request-body-parse-failed","analyzedSha":"e2740d5a1bd0b4254e517e3af8b60789284bc7bd","analyzedAt":"2026-08-28T10:18:08.750Z","schemaVersion":2},"datasetVersion":"2026-08-28T11:17:15.048Z"}