thedotmack/claude-mem · warning

Anthropic API rejected request with HTTP 400: this model doe

Error message

Anthropic API rejected request with HTTP 400: this model does not support the `effort` parameter. CLAUDE_CODE_EFFORT_LEVEL is likely leaking into the SDK subprocess env via ~/.claude-mem/.env — remove it or scope it to models that support effort. See https://github.com/thedotmack/claude-mem/issues/2357.

What it means

The observer drives the Claude Agent SDK as a subprocess; that subprocess inherits claude-mem's environment, including ~/.claude-mem/.env. When that env contains CLAUDE_CODE_EFFORT_LEVEL and the active model does not support the effort parameter, the Anthropic API rejects requests with HTTP 400; the provider classifier detects the 'effort parameter' marker in the message or body, logs this hint once, and classifies the error as unrecoverable.

Source

Thrown at src/services/worker/ClaudeProvider.ts:138

  // the pattern in GeminiProvider.classifyGeminiError / classifyOpenRouterError
  // (see #2357: the SDK forwards `effort` to the Messages API when
  // CLAUDE_CODE_EFFORT_LEVEL leaks into the subprocess env, and models like
  // Haiku/Sonnet 4.5 reject with 400 — without this branch the default
  // `transient` classification retried indefinitely).
  if (errAny.status === 400) {
    // Inspect both the message and any structured body for the effort marker.
    const bodyText = (() => {
      const body = errAny.body;
      if (typeof body === 'string') return body;
      if (body && typeof body === 'object') {
        try { return JSON.stringify(body); } catch { return ''; }
      }
      return '';
    })();
    const haystack = `${message}\n${bodyText}`;
    if (/effort parameter/i.test(haystack) && !effortHintLogged) {
      effortHintLogged = true;
      logger.warn(
        'SDK',
        'Anthropic API rejected request with HTTP 400: this model does not support the `effort` parameter. ' +
          'CLAUDE_CODE_EFFORT_LEVEL is likely leaking into the SDK subprocess env via ~/.claude-mem/.env — ' +
          'remove it or scope it to models that support effort. See https://github.com/thedotmack/claude-mem/issues/2357.',
        { status: 400 }
      );
    }
    return new ClassifiedProviderError(
      message || 'Anthropic bad request (status 400)',
      { kind: 'unrecoverable', cause: err },
    );
  }

  // Status-less Anthropic 400s — SDK wrapping can drop `.status`, leaving only
  // the message or an `invalid_request_error` body; classify those as
  // unrecoverable so the worker stops retrying a permanent config error (#2656).
  // The status guard keeps statused 4xx/5xx on their own branches.
  if (

View on GitHub (pinned to 8bc631a71a)

Solutions

  1. Remove CLAUDE_CODE_EFFORT_LEVEL from ~/.claude-mem/.env and restart the worker
  2. If you need effort, scope it to a model that supports the parameter (per-model env or settings) instead of the global .env
  3. Verify the fix by confirming the observer no longer logs 400s and sessions complete

Example fix

# ~/.claude-mem/.env - before
CLAUDE_CODE_EFFORT_LEVEL=low

# after (line removed)
# scope effort per supported model in the SDK settings instead
Defensive patterns

Strategy: validation

Validate before calling

import fs from 'node:fs';

function assertNoLeakedEffortLevel(envPath = path.join(os.homedir(), '.claude-mem', '.env')): void {
  if (!fs.existsSync(envPath)) return;
  const raw = fs.readFileSync(envPath, 'utf-8');
  if (/^\s*CLAUDE_CODE_EFFORT_LEVEL\s*=/m.test(raw)) {
    throw new Error('CLAUDE_CODE_EFFORT_LEVEL in ~/.claude-mem/.env breaks models without effort support — remove or scope it');
  }
}

Try / catch

try {
  await runObserverQuery(session);
} catch (error: unknown) {
  const msg = error instanceof Error ? error.message : String(error);
  if (/effort parameter/i.test(msg)) {
    // unrecoverable config issue: strip CLAUDE_CODE_EFFORT_LEVEL from .env, restart worker, do not retry as-is
    throw new Error('Remove CLAUDE_CODE_EFFORT_LEVEL from ~/.claude-mem/.env (issue #2357)');
  }
  throw error;
}

Prevention

When it happens

Trigger: ~/.claude-mem/.env sets CLAUDE_CODE_EFFORT_LEVEL (e.g. low/medium/high) while the configured model rejects effort; the var was added for a different model and later the model changed; the SDK version started forwarding the var to the API.

Common situations: Users tuning effort for Claude Code in .env then switching observer models; copying a teammate's .env; upgrading the SDK so a previously ignored variable is now honored.

Understand the failure class

Related errors


AI-assisted analysis of thedotmack/claude-mem@8bc631a71a (2026-08-20). Data as JSON: /api/errors/f93a87056075683e. Report an issue: GitHub.