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.
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.
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
- 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.
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
- request.session.provider must match request.provider
- AWS AgentCore evals require exact model…
- ACPX profile requires exact model ; received
- ACPX model must not be empty
- ACPX provider identity contains an invalid permission mode
AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-09-02).
Data as JSON: /api/errors/845d101b868c446a.
Report an issue: GitHub.
Appendix: 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)