{"record":{"id":"6641f0772c8e0e61","repo":"paperclipai/paperclip","slug":"eval-session-acpxagent-must-be-codex-or-claude","errorCode":null,"errorMessage":"eval-session acpxAgent must be codex or claude","messagePattern":"eval-session acpxAgent must be codex or claude","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/paperclip-runner/src/cli/eval-session-contract.ts","lineNumber":246,"sourceCode":"      \"eval-session provider is unsupported by CapabilityLiveSessionService\",\n    );\n  }\n  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\");","sourceCodeStart":228,"sourceCodeEnd":264,"githubUrl":"https://github.com/paperclipai/paperclip/blob/01ad8584922b5d85292b1723cae71fa0d9b07a19/packages/paperclip-runner/src/cli/eval-session-contract.ts#L228-L264","documentation":"acpxAgent, when provided, must be exactly 'codex' or 'claude'. parseEvalSessionRequest fail-closed rejects any other string value because only these two ACPX agent profiles are qualified for eval sessions at the executable boundary. This is a strict allowlist, not a free-text field.","triggerScenarios":"Calling parseEvalSessionRequest with input.acpxAgent set to any string other than 'codex', 'claude', or the separately rejected 'pi' — e.g. 'gpt', 'Codex' (wrong case), 'codex-cli', or an empty/typo value like 'cdoex'.","commonSituations":"Typo or wrong casing of the agent name; passing a CLI binary name instead of the profile name; config generated from a list of all ACPX agents rather than the supported subset; renaming across versions.","solutions":["Set acpxAgent to exactly 'codex' or 'claude' (lowercase).","Omit acpxAgent entirely if no ACPX-specific agent is needed.","Fix the casing/typo in the config or generator script.","Validate the value against the allowlist before constructing the request."],"exampleFix":"// before\nconst request = { schema, provider: \"acpx\", acpxAgent: \"Codex\", ... };\n// after\nconst request = { schema, provider: \"acpx\", acpxAgent: \"codex\", ... };","handlingStrategy":"type-guard","validationCode":"function assertValidAcpxAgent(request: { acpxAgent?: unknown }): void {\n  const a = request.acpxAgent;\n  if (a !== undefined && a !== \"codex\" && a !== \"claude\") {\n    throw new Error(`acpxAgent '${String(a)}' invalid; must be 'codex' or 'claude' (exact lowercase)`);\n  }\n}","typeGuard":"function isAcpxAgent(v: unknown): v is \"codex\" | \"claude\" {\n  return typeof v === \"string\" && (v === \"codex\" || v === \"claude\");\n}","tryCatchPattern":"try {\n  const parsed = parseEvalSessionRequest(raw);\n} catch (err) {\n  if (err instanceof Error && err.message === \"eval-session acpxAgent must be codex or claude\") {\n    console.error(`acpxAgent '${raw.acpxAgent}' not allowed; use exactly 'codex' or 'claude'.`);\n  } else throw err;\n}","preventionTips":["Type acpxAgent as 'codex' | 'claude' | undefined in TypeScript so invalid values fail at compile time.","Never build the value by string concatenation or from user/env input without narrowing.","Validate against the allowlist at config-load time, before the CLI boundary.","Watch for casing: 'Codex' and 'CODEX' are rejected."],"tags":["validation","contract","enum"],"backgroundTag":"invalid-enum-value","analyzedSha":"01ad8584922b5d85292b1723cae71fa0d9b07a19","analyzedAt":"2026-09-02T18:44:00.616Z","contentChangedAt":"2026-09-02T18:44:00.616Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}