{"record":{"id":"845d101b868c446a","repo":"paperclipai/paperclip","slug":"request-session-requestedmodel-must-match-request","errorCode":null,"errorMessage":"request.session.requestedModel must match request.model","messagePattern":"request\\.session\\.requestedModel must match request\\.model","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/paperclip-runner/src/cli/eval-session-contract.ts","lineNumber":307,"sourceCode":"  if (provider === \"claude_managed\" && model !== \"claude-sonnet-5\") {\n    throw new Error(\"Claude Managed evals require exact model claude-sonnet-5\");\n  }\n  if (\n    provider === \"aws_agentcore\" &&\n    model !== \"global.anthropic.claude-sonnet-4-6\"\n  ) {\n    throw new Error(\n      \"AWS AgentCore evals require exact model global.anthropic.claude-sonnet-4-6\",\n    );\n  }\n  if (sessionInput.provider !== undefined && sessionInput.provider !== provider) {\n    throw new Error(\"request.session.provider must match request.provider\");\n  }\n  if (\n    session.requestedModel !== undefined &&\n    session.requestedModel !== model\n  ) {\n    throw new Error(\"request.session.requestedModel must match request.model\");\n  }\n  if (session.acpxAgent === \"pi\") {\n    throw new Error(\"The Pi ACPX profile is not available\");\n  }\n\n  return {\n    schema: EVAL_SESSION_REQUEST_SCHEMA,\n    attemptId: text(input.attemptId, \"request.attemptId\"),\n    prompt: text(input.prompt, \"request.prompt\"),\n    model,\n    provider,\n    driver,\n    ...(typeof input.opencodeVersion === \"string\"\n      ? { opencodeVersion: text(input.opencodeVersion, \"request.opencodeVersion\") }\n      : {}),\n    ...(acpxAgent === undefined ? {} : { acpxAgent }),\n    ...(managedProfile === undefined ? {} : { managedProfile }),\n    ...(agentCoreProfile === undefined ? {} : { agentCoreProfile }),","sourceCodeStart":289,"sourceCodeEnd":325,"githubUrl":"https://github.com/paperclipai/paperclip/blob/01ad8584922b5d85292b1723cae71fa0d9b07a19/packages/paperclip-runner/src/cli/eval-session-contract.ts#L289-L325","documentation":"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.","triggerScenarios":"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.","commonSituations":"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).","solutions":["Set request.session.requestedModel to the exact string in request.model, or remove session.requestedModel so it inherits the top-level model.","Fix the request-builder to assign both fields from a single model constant.","Search the request JSON for all occurrences of the model string and make them consistent.","Re-run with a freshly generated request file if the JSON was hand-edited across model upgrades."],"exampleFix":"// before\n{\n  \"model\": \"claude-sonnet-5\",\n  \"session\": { \"requestedModel\": \"claude-sonnet-4-6\", ... }\n}\n// after\n{\n  \"model\": \"claude-sonnet-5\",\n  \"session\": { \"requestedModel\": \"claude-sonnet-5\", ... }\n}","handlingStrategy":"validation","validationCode":"function assertSessionModelMatches(req: { model?: string; session?: { requestedModel?: string } }): void {\n  if (req.session?.requestedModel !== undefined && req.session.requestedModel !== req.model) {\n    throw new Error(`session.requestedModel (${req.session.requestedModel}) != model (${req.model})`);\n  }\n}","typeGuard":"function hasConsistentModel(req: { model?: string; session?: { requestedModel?: string } }): boolean {\n  return req.session?.requestedModel === undefined || req.session.requestedModel === req.model;\n}","tryCatchPattern":"try {\n  const parsed = parseEvalSessionRequest(rawRequest);\n  // proceed\n} catch (err) {\n  if (err instanceof Error && err.message === \"request.session.requestedModel must match request.model\") {\n    // sync session.requestedModel = request.model (or delete it), then retry\n  } else throw err;\n}","preventionTips":["Set session.requestedModel and request.model from one shared constant.","Omit session.requestedModel when it would just mirror the top-level model.","Canonicalize model IDs (no aliases/shorthand) in your eval config.","Add a JSON-schema or custom pre-flight check over the request file before invoking the CLI."],"tags":["validation","config","consistency","evals"],"backgroundTag":"config-field-mismatch","analyzedSha":"01ad8584922b5d85292b1723cae71fa0d9b07a19","analyzedAt":"2026-09-02T18:44:00.616Z","contentChangedAt":"2026-09-02T18:44:00.616Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}