thedotmack/claude-mem · error

ValidationError

ValidationError

Error message

ValidationError

What it means

The legacy /api/sessions/summarize compat route validates req.body against summarizeSchema with safeParse and returns HTTP 400 { error:'ValidationError', issues:[...] } when the payload does not match. This is the adapter's input-contract enforcement before any ingestion happens.

Solutions

  1. Read the issues array in the 400 response — it lists exact failing paths and expected types
  2. Align the client payload with summarizeSchema (required fields and types)
  3. If the schema changed, update the legacy client or relax/extend the schema in the adapter
  4. Test the payload with a quick safeParse in a script before calling the endpoint

Example fix

// before
await fetch('/api/sessions/summarize', { method: 'POST', body: JSON.stringify({}) });
// after
await fetch('/api/sessions/summarize', { method: 'POST', body: JSON.stringify({ contentSessionId: 'sess_123' }) });
Defensive patterns

Strategy: validation

Validate before calling

// mirror summarizeSchema on the client before POSTing
import { summarizeSchema } from './schemas';
const parsed = summarizeSchema.safeParse(body);
if (!parsed.success) throw new Error(`Invalid summarize payload: ${JSON.stringify(parsed.error.issues)}`);

Type guard

const isValidSummarizeBody = (b) => typeof b?.contentSessionId === 'string' && b.contentSessionId.length > 0;

Try / catch

// handle 400 validation errors explicitly
if (res.status === 400 && body.error === 'ValidationError') {
  console.error('Payload rejected:', body.issues);
}

Prevention

When it happens

Trigger: POST /api/sessions/summarize with a body missing required fields (e.g. contentSessionId) or with wrong types, per summarizeSchema in SessionsSummarizeAdapter.ts.

Common situations: Older Claude Code clients sending a payload shape that drifted from the current summarizeSchema; manual curl testing with incomplete JSON; client bug after a schema field was renamed or made required.

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@d8bc9755e7 (2026-09-17). Data as JSON: /api/errors/42a384393683c809. Report an issue: GitHub.

Appendix: source

Thrown at src/server/compat/SessionsSummarizeAdapter.ts:53

  endSession: EndSessionService;
  authMode?: string;
  allowLocalDevBypass?: boolean;
}

export class SessionsSummarizeAdapter implements RouteHandler {
  constructor(private readonly options: SessionsSummarizeAdapterOptions) {}

  setupRoutes(app: Application): void {
    const writeAuth = requirePostgresServerAuth(this.options.pool, {
      authMode: this.options.authMode,
      allowLocalDevBypass: this.options.allowLocalDevBypass,
      requiredScopes: ['memories:write'],
    });

    app.post('/api/sessions/summarize', writeAuth, this.asyncHandler(async (req, res) => {
      const parsed = summarizeSchema.safeParse(req.body);
      if (!parsed.success) {
        res.status(400).json({ error: 'ValidationError', issues: parsed.error.issues });
        return;
      }
      const teamId = req.authContext?.teamId ?? null;
      const projectId = req.authContext?.projectId ?? null;
      if (!teamId) {
        res.status(403).json({ error: 'Forbidden', message: 'API key is not bound to a team' });
        return;
      }
      if (!projectId) {
        res.status(400).json({
          error: 'BadRequest',
          message: 'Legacy /api/sessions/summarize requires a project-scoped API key',
        });
        return;
      }

      // Subagent contexts in legacy code emit summarize calls but the worker
      // skipped them. We preserve the legacy semantics so existing clients

View on GitHub (pinned to d8bc9755e7)