{"record":{"id":"3573fb177b155ebd","repo":"paperclipai/paperclip","slug":"eval-session-acpxagent-requires-provider-acpx","errorCode":null,"errorMessage":"eval-session acpxAgent requires provider acpx","messagePattern":"eval-session acpxAgent requires provider acpx","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/paperclip-runner/src/cli/eval-session-contract.ts","lineNumber":249,"sourceCode":"  const provider = providerValue;\n  const driver = expectedEvalSessionDriver(provider);\n  if (input.driver !== undefined && input.driver !== driver) {\n    throw new Error(\"eval-session provider/driver mismatch\");\n  }\n  // The original Evalbook v1 producer serialized absent provider-specific\n  // options as JSON null. Preserve compatibility with those immutable request\n  // artifacts while continuing to reject non-null values for the wrong lane.\n  const acpxAgent = input.acpxAgent === null ? undefined : input.acpxAgent;\n  if (acpxAgent === \"pi\") throw new Error(\"The Pi ACPX profile is not available\");\n  if (\n    acpxAgent !== undefined &&\n    acpxAgent !== \"codex\" &&\n    acpxAgent !== \"claude\"\n  ) {\n    throw new Error(\"eval-session acpxAgent must be codex or claude\");\n  }\n  if (provider !== \"acpx\" && acpxAgent !== undefined) {\n    throw new Error(\"eval-session acpxAgent requires provider acpx\");\n  }\n  const managedProfileInput = input.managedProfile === null\n    ? undefined\n    : input.managedProfile;\n  const agentCoreProfileInput = input.agentCoreProfile === null\n    ? undefined\n    : input.agentCoreProfile;\n  const managedProfile = provider === \"claude_managed\"\n    ? parseManagedProfile(managedProfileInput)\n    : undefined;\n  const agentCoreProfile = provider === \"aws_agentcore\"\n    ? parseAgentCoreProfile(agentCoreProfileInput)\n    : undefined;\n  if (provider !== \"claude_managed\" && managedProfileInput !== undefined) {\n    throw new Error(\"eval-session managedProfile requires provider claude_managed\");\n  }\n  if (provider !== \"aws_agentcore\" && agentCoreProfileInput !== undefined) {\n    throw new Error(\"eval-session agentCoreProfile requires provider aws_agentcore\");","sourceCodeStart":231,"sourceCodeEnd":267,"githubUrl":"https://github.com/paperclipai/paperclip/blob/01ad8584922b5d85292b1723cae71fa0d9b07a19/packages/paperclip-runner/src/cli/eval-session-contract.ts#L231-L267","documentation":"acpxAgent is only meaningful when provider is 'acpx'. If any other provider (codex, opencode, claude_managed, aws_agentcore) is selected and acpxAgent is defined, parseEvalSessionRequest rejects the request rather than silently ignoring the field. This keeps the fail-closed contract from mixing provider-specific options.","triggerScenarios":"A request like {provider:'codex', acpxAgent:'codex'} or {provider:'claude_managed', acpxAgent:'claude'} — the agent field leaks in from an ACPX-shaped template while provider was changed to something else.","commonSituations":"Reusing one request-builder for all providers and always setting acpxAgent; switching provider in a config file but leaving the acpx block in place; merged/templated config that carries stale ACPX keys.","solutions":["Remove the acpxAgent field when provider is not 'acpx'.","Set provider to 'acpx' if the ACPX agent is actually intended.","Make the request builder conditionally include acpxAgent only for provider 'acpx'.","Strip provider-irrelevant fields from the config before constructing the request."],"exampleFix":"// before\nconst request = { schema, provider: \"codex\", acpxAgent: \"codex\", ... };\n// after\nconst request = { schema, provider: \"codex\", ... };\n// or, if ACPX was intended:\nconst request = { schema, provider: \"acpx\", acpxAgent: \"codex\", ... };","handlingStrategy":"validation","validationCode":"function assertAcpxAgentProviderPair(request: { provider?: string; acpxAgent?: string }): void {\n  const provider = request.provider ?? \"codex\";\n  if (provider !== \"acpx\" && request.acpxAgent !== undefined) {\n    throw new Error(`acpxAgent set but provider is '${provider}'; acpxAgent requires provider 'acpx'`);\n  }\n}","typeGuard":"function acpxAgentAllowed(r: { provider?: string; acpxAgent?: unknown }): boolean {\n  return r.acpxAgent === undefined || (r.provider ?? \"codex\") === \"acpx\";\n}","tryCatchPattern":"try {\n  const parsed = parseEvalSessionRequest(raw);\n} catch (err) {\n  if (err instanceof Error && err.message === \"eval-session acpxAgent requires provider acpx\") {\n    console.error(`Remove acpxAgent or set provider to 'acpx' (got provider='${raw.provider ?? \"codex\"}').`);\n  } else throw err;\n}","preventionTips":["Build requests per-provider: only include acpxAgent in the acpx branch of your builder.","Strip leftover ACPX keys when switching provider in config files.","Use a discriminated union type per provider (AcpxRequest | CodexRequest | ...) so invalid field/provider combos are type errors.","Diff provider-specific blocks when editing shared eval configs."],"tags":["validation","contract","config"],"backgroundTag":"incompatible-provider-options","analyzedSha":"01ad8584922b5d85292b1723cae71fa0d9b07a19","analyzedAt":"2026-09-10T03:14:50.855Z","contentChangedAt":"2026-09-10T03:14:50.855Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}