paperclipai/paperclip · error

request.session.requestedModel must match request.model

Error message

request.session.requestedModel must match request.model

What it means

parseEvalSessionRequest validates that request.session.requestedModel, when present, equals the top-level request.model exactly (eval-session-contract.ts:294-299). The session's requestedModel is forwarded to the live-session service, so a divergence would make the eval record claim one model while the session actually requests another, breaking result attribution. As with provider, omitting requestedModel is allowed and inherits request.model.

Source

Thrown at packages/paperclip-runner/src/cli/eval-session-contract.ts:307

  if (provider === "claude_managed" && model !== "claude-sonnet-5") {
    throw new Error("Claude Managed evals require exact model claude-sonnet-5");
  }
  if (
    provider === "aws_agentcore" &&
    model !== "global.anthropic.claude-sonnet-4-6"
  ) {
    throw new Error(
      "AWS AgentCore evals require exact model global.anthropic.claude-sonnet-4-6",
    );
  }
  if (sessionInput.provider !== undefined && sessionInput.provider !== provider) {
    throw new Error("request.session.provider must match request.provider");
  }
  if (
    session.requestedModel !== undefined &&
    session.requestedModel !== model
  ) {
    throw new Error("request.session.requestedModel must match request.model");
  }
  if (session.acpxAgent === "pi") {
    throw new Error("The Pi ACPX profile is not available");
  }

  return {
    schema: EVAL_SESSION_REQUEST_SCHEMA,
    attemptId: text(input.attemptId, "request.attemptId"),
    prompt: text(input.prompt, "request.prompt"),
    model,
    provider,
    driver,
    ...(typeof input.opencodeVersion === "string"
      ? { opencodeVersion: text(input.opencodeVersion, "request.opencodeVersion") }
      : {}),
    ...(acpxAgent === undefined ? {} : { acpxAgent }),
    ...(managedProfile === undefined ? {} : { managedProfile }),
    ...(agentCoreProfile === undefined ? {} : { agentCoreProfile }),

View on GitHub (pinned to 01ad858492)

Solutions

  1. Set request.session.requestedModel to the exact string in request.model, or remove session.requestedModel so it inherits the top-level model.
  2. Fix the request-builder to assign both fields from a single model constant.
  3. Search the request JSON for all occurrences of the model string and make them consistent.
  4. Re-run with a freshly generated request file if the JSON was hand-edited across model upgrades.

Example fix

// before
{
  "model": "claude-sonnet-5",
  "session": { "requestedModel": "claude-sonnet-4-6", ... }
}
// after
{
  "model": "claude-sonnet-5",
  "session": { "requestedModel": "claude-sonnet-5", ... }
}
Defensive patterns

Strategy: validation

Validate before calling

function assertSessionModelMatches(req: { model?: string; session?: { requestedModel?: string } }): void {
  if (req.session?.requestedModel !== undefined && req.session.requestedModel !== req.model) {
    throw new Error(`session.requestedModel (${req.session.requestedModel}) != model (${req.model})`);
  }
}

Type guard

function hasConsistentModel(req: { model?: string; session?: { requestedModel?: string } }): boolean {
  return req.session?.requestedModel === undefined || req.session.requestedModel === req.model;
}

Try / catch

try {
  const parsed = parseEvalSessionRequest(rawRequest);
  // proceed
} catch (err) {
  if (err instanceof Error && err.message === "request.session.requestedModel must match request.model") {
    // sync session.requestedModel = request.model (or delete it), then retry
  } else throw err;
}

Prevention

When it happens

Trigger: Calling parseEvalSessionRequest with request.model='global.anthropic.claude-sonnet-4-6' but request.session.requestedModel set to 'claude-sonnet-4-5', an alias like 'sonnet-4.6', or a stale model string; also triggered when session.requestedModel is present but request.model was edited without updating the session.

Common situations: Switching the eval to a different model and updating only request.model; copy-pasting a session block from another eval run with a different model; alias vs canonical model ID confusion (e.g. 'sonnet' shorthand vs full ID).

Related errors


AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-09-02). Data as JSON: /api/errors/845d101b868c446a. Report an issue: GitHub.