thedotmack/claude-mem · warning

message

Error message

message

What it means

badRequest is BaseRouteHandler's helper that responds 400 with `{ error: message }`. The thrown 'message' here is the helper's parameter — the concrete text comes from callers like parseIntParam when a required numeric/typed query param fails to parse.

Solutions

  1. Send a valid integer for the parameter (e.g. ?limit=50)
  2. Inspect the route's parseIntParam call to see the expected param name and constraints
  3. Omit optional params entirely instead of sending empty values

Example fix

// before
GET /api/observations?limit=abc
// after
GET /api/observations?limit=50
Defensive patterns

Strategy: validation

Validate before calling

function isValidIntParam(v: unknown): v is number {
  const n = Number(v);
  return Number.isInteger(n) && n > 0;
}
// before sending: if (!isValidIntParam(limit)) omit param;

Type guard

function isPositiveInt(v: unknown): v is number {
  return typeof v === 'number' && Number.isInteger(v) && v > 0;
}

Prevention

When it happens

Trigger: Calling a worker API route with a query parameter that parseIntParam cannot parse (non-numeric where an int is required, empty value).

Common situations: Passing 'abc' or '' as ?limit= or ?id=; URL-encoded garbage in pagination params; SDK/client sending string types where ints are expected.

Understand the failure class

Background: "Invalid query parameter" / "Failed to parse value of ...": fixing bad query string parameters across APIs — this error's family across 36 libraries.

Related errors


AI-assisted analysis of thedotmack/claude-mem@d8bc9755e7 (2026-09-17). Data as JSON: /api/errors/caa9a2e2e8bcbfef. Report an issue: GitHub.

Appendix: source

Thrown at src/services/worker/http/BaseRouteHandler.ts:77

      ?? req.get?.('x-claude-mem-platform-source');
    return BaseRouteHandler.firstString(req.query.platformSource)
      ?? BaseRouteHandler.firstString(req.query.platform_source)
      ?? BaseRouteHandler.firstString(body.platformSource)
      ?? BaseRouteHandler.firstString(body.platform_source)
      ?? BaseRouteHandler.firstString(header);
  }

  protected getPlatformSourceFromRequest(req: Request): string {
    return normalizePlatformSource(BaseRouteHandler.rawPlatformSourceFromRequest(req));
  }

  protected getOptionalPlatformSourceFromRequest(req: Request): string | undefined {
    const rawPlatformSource = BaseRouteHandler.rawPlatformSourceFromRequest(req);
    return rawPlatformSource ? normalizePlatformSource(rawPlatformSource) : undefined;
  }

  protected badRequest(res: Response, message: string): void {
    res.status(400).json({ error: message });
  }

  protected notFound(res: Response, message: string): void {
    res.status(404).json({ error: message });
  }

  protected handleError(res: Response, error: Error, context?: string): void {
    const statusCode = error instanceof AppError ? error.statusCode : 500;
    // Client errors (4xx AppErrors) are routine bad input, not server faults, so
    // they log at WARN and are NOT routed to the error sink — surfacing a
    // validation rejection like a bad corpus name as a captured $exception just
    // pollutes error tracking with noise. Only true server faults (5xx, or any
    // non-AppError, which maps to 500) go through logger.failure, whose Error
    // payload routes through logger.error → the error sink → captureException
    // (Phase 3): a REDACTED $exception to PostHog Error Tracking, consent-gated,
    // kill-switch-gated, and rate-limited.
    const isClientError = statusCode >= 400 && statusCode < 500;
    if (isClientError) {

View on GitHub (pinned to d8bc9755e7)