{"record":{"id":"6a754ef71b37db3e","repo":"affaan-m/ECC","slug":"validation-error","errorCode":"VALIDATION_ERROR","errorMessage":"Request validation failed","messagePattern":"Request validation failed","errorType":"http","errorClass":null,"httpStatus":422,"severity":"error","filePath":"skills/error-handling/SKILL.md","lineNumber":138,"sourceCode":"  if (error instanceof AppError) {\n    return NextResponse.json(\n      {\n        error: {\n          code: error.code,\n          message: error.message,\n          ...(error.details ? { details: error.details } : {}),\n        },\n      },\n      { status: error.statusCode },\n    )\n  }\n\n  // Zod validation error\n  if (error instanceof z.ZodError) {\n    return NextResponse.json(\n      {\n        error: {\n          code: 'VALIDATION_ERROR',\n          message: 'Request validation failed',\n          details: error.issues.map(i => ({\n            field: i.path.join('.'),\n            message: i.message,\n          })),\n        },\n      },\n      { status: 422 },\n    )\n  }\n\n  // Unexpected error — log details, return generic message\n  console.error('Unexpected error:', error)\n  return NextResponse.json(\n    { error: { code: 'INTERNAL_ERROR', message: 'An unexpected error occurred' } },\n    { status: 500 },\n  )\n}","sourceCodeStart":120,"sourceCodeEnd":156,"githubUrl":"https://github.com/affaan-m/ECC/blob/d8409a4b0813771235555e32e3d8046a73988bfa/skills/error-handling/SKILL.md#L120-L156","documentation":"This is the ZodError branch of the handleApiError helper shown in the error-handling skill: when a Next.js route validates its request body with a Zod schema and parsing fails, the handler returns HTTP 422 with code VALIDATION_ERROR and a details array mapping each failing field path to its message. It exists so clients get actionable, field-level feedback instead of a generic 400.","triggerScenarios":"POSTing a body that fails the route's Zod schema: missing required field, wrong type (string where number expected), invalid email format, string shorter than a min() constraint, or a nested object whose sub-field fails (reported as dotted paths like 'address.street').","commonSituations":"Frontend and backend schema drift after a new required field was added server-side; enum value typo from a hand-written curl; JSON key casing mismatch (createdAt vs created_at); empty string sent where min(1) applies; API consumer built against an older version of the contract.","solutions":["Read response.error.details[] — each entry names the exact field path and the failing constraint; fix those fields in the request payload","Compare the payload against the route's Zod schema (it is the source of truth for the contract)","If you own the API and just added the field, make it optional or give it a default so older clients keep working","Validate on the client with the same (shared) schema before sending to fail early with better UX"],"exampleFix":"// before - client sends body missing a required field\nawait fetch('/api/users', { method: 'POST', body: JSON.stringify({ email: 'a@b.co' }) })\n// -> 422 { code: 'VALIDATION_ERROR', details: [{ field: 'name', message: 'Required' }] }\n\n// after\nawait fetch('/api/users', { method: 'POST', body: JSON.stringify({ email: 'a@b.co', name: 'Ada' }) })","handlingStrategy":"validation","validationCode":"// Server-side: use safeParse and branch before it can throw\nconst parsed = CreateUserSchema.safeParse(await req.json())\nif (!parsed.success) {\n  return NextResponse.json(\n    { error: { code: 'VALIDATION_ERROR', message: 'Request validation failed', details: parsed.error.issues } },\n    { status: 422 },\n  )\n}\n// parsed.data is now fully typed for the handler","typeGuard":"const isZodError = (e: unknown): e is z.ZodError => e instanceof z.ZodError","tryCatchPattern":"try {\n  await handler(req)\n} catch (error) {\n  if (error instanceof z.ZodError) {\n    // 422 with field-level details from error.issues — never rethrow raw\n    return respond422(error.issues.map(i => ({ field: i.path.join('.'), message: i.message })))\n  }\n  throw error // let the generic 500 branch log it","preventionTips":["Share the exact Zod schema module between client and server so the contract cannot drift","Validate on the client with safeParse before sending and show field errors in the form","Read details[].field from 422 responses programmatically instead of string-matching messages","When adding required fields to a schema, ship them as .optional() or with .default() first to avoid breaking existing clients"],"tags":["zod","validation","nextjs","http-422","api"],"backgroundTag":"schema-validation-failed","analyzedSha":"d8409a4b0813771235555e32e3d8046a73988bfa","analyzedAt":"2026-08-26T12:15:34.022Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}