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

  1. Inspect response.issues[] — each states the exact path, Zod code and human message
  2. Fix the offending field to match the exported schema (buildCorpusSchema / queryCorpusSchema)
  3. 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

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.