thedotmack/claude-mem · error
ValidationError
ValidationError
Error message
ValidationError
What it means
HTTP 400 produced by the validateBody(schema) Express middleware when the JSON body of a POST route fails its Zod schema. The response is machine-readable: { error: 'ValidationError', issues: [{ path, message, code }] }, one entry per failed check. On success the parsed (and coerced/defaulted) value replaces req.body.
Source
Thrown at src/services/worker/http/middleware/validateBody.ts:9
import type { RequestHandler } from 'express';
import type { ZodTypeAny } from 'zod';
export const validateBody = <S extends ZodTypeAny>(schema: S): RequestHandler =>
(req, res, next) => {
const result = schema.safeParse(req.body);
if (!result.success) {
res.status(400).json({
error: 'ValidationError',
issues: result.error.issues.map(i => ({
path: i.path,
message: i.message,
code: i.code,
})),
});
return;
}
req.body = result.data;
next();
};
View on GitHub (pinned to e2d1df569a)
Solutions
- Inspect response.issues[] — each states the exact path, Zod code and human message
- Fix the offending field to match the exported schema (buildCorpusSchema / queryCorpusSchema)
- Validate client-side with the same Zod schema before sending to get errors at build time
Example fix
// before
await fetch(`${base}/api/corpus`, {
method: 'POST',
body: JSON.stringify({ name: 'x', limit: '50' }), // 400: limit must be number
});
// after
await fetch(`${base}/api/corpus`, {
method: 'POST',
body: JSON.stringify({ name: 'x', limit: 50 }),
}); Defensive patterns
Strategy: validation
Validate before calling
import { z } from 'zod';
const payloadSchema = z.object({
name: z.string().min(1),
limit: z.number().int().positive().max(1000).optional(),
date_start: z.string().date().optional(),
});
const safe = payloadSchema.parse(raw); // throws before the request is even sent Type guard
interface ValidationIssues {
error: 'ValidationError';
issues: Array<{ path: (string | number)[]; message: string; code: string }>;
}
function isValidationIssues(body: unknown): body is ValidationIssues {
return typeof body === 'object' && body !== null &&
(body as { error?: unknown }).error === 'ValidationError' &&
Array.isArray((body as { issues?: unknown }).issues);
} Try / catch
const res = await callApi();
if (res.status === 400) {
const body = await res.json();
if (isValidationIssues(body))
throw new Error(body.issues.map(i => `${i.path.join('.')}: ${i.message}`).join('; '));
} Prevention
- Share the worker's Zod schemas with the client and parse payloads locally first
- Coerce CLI string args with Number() before putting them into JSON bodies
- Write a failing-shape test per validated endpoint so schema drift is caught in CI
When it happens
Trigger: POSTing to schema-validated routes — /api/corpus (buildCorpusSchema), /api/corpus/:name/query (queryCorpusSchema) — with a wrong type (string where number expected), an unknown enum value, a missing required field such as query, or an exceeded limit.
Common situations: Client and worker built from different versions so the schema drifted; passing date strings in the wrong format for date_start/date_end; sending limit as a string because it came from CLI argv without Number() conversion; extra whitespace/BOM breaking JSON parsing upstream so body is a string.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
AI-assisted analysis of thedotmack/claude-mem@e2d1df569a (2026-08-20).
Data as JSON: /api/errors/c0855d4626d1adc2.
Report an issue: GitHub.