{"record":{"id":"f286414c40b05b43","repo":"paperclipai/paperclip","slug":"paperclip-runner-codex-permission-mode-unqualified","errorCode":"paperclip_runner_codex_permission_mode_unqualified","errorMessage":"paperclip_runner_codex_permission_mode_unqualified: set codexPermissionMode to never before starting or recovering this native run","messagePattern":"paperclip_runner_codex_permission_mode_unqualified: set codexPermissionMode to never before starting or recovering this native run","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/paperclip-runner/src/backends/codex-native-backend.ts","lineNumber":124,"sourceCode":"    options.workingDirectoryAuthority === \"remote_runner\" &&\n    !options.transportFactory\n  ) {\n    throw new Error(\n      \"Remote runner workspace authority requires a runnerd transport\",\n    );\n  }\n  const driverIdentity = transportDriverIdentity(input);\n  const isCodex = input.provider.kind === \"codex\";\n  const supportsCollaborativePlanning =\n    isCodex ||\n    input.provider.kind === \"opencode\" ||\n    input.provider.kind === \"acpx\";\n  if (\n    input.provider.kind === \"codex\" &&\n    input.provider.approvalPolicy !== undefined &&\n    input.provider.approvalPolicy !== \"never\"\n  ) {\n    throw new Error(\n      \"paperclip_runner_codex_permission_mode_unqualified: set codexPermissionMode to never before starting or recovering this native run\",\n    );\n  }\n\n  return new HarnessDriverBackend(\n    new CodexAppServerDriver({\n      ...(input.provider.model ? { model: input.provider.model } : {}),\n      // Runnerd owns provider permissions for non-Codex facades. Their\n      // Codex-compatible surface must never open a second approval channel.\n      approvalPolicy:\n        input.provider.kind === \"codex\"\n          ? (input.provider.approvalPolicy ?? \"never\")\n          : \"never\",\n      baseInstructions: nativeSystemInstructions(input),\n      includeSkillInstructions: isCodex && \"runtimeContext\" in input,\n      requestedCollaborationMode:\n        supportsCollaborativePlanning && \"executionMode\" in input\n          ? input.executionMode","sourceCodeStart":106,"sourceCodeEnd":142,"githubUrl":"https://github.com/paperclipai/paperclip/blob/01ad8584922b5d85292b1723cae71fa0d9b07a19/packages/paperclip-runner/src/backends/codex-native-backend.ts#L106-L142","documentation":"For Codex providers, the backend requires approvalPolicy to be 'never' (or unset) because native runs must run fully non-interactive without permission prompts. If a Codex provider is configured with any other approval policy (e.g. 'on-request', 'on-failure', 'untrusted'), the backend refuses to start so the run cannot hang waiting for interactive approvals.","triggerScenarios":"Starting or recovering a native Codex run where input.provider.approvalPolicy is defined and not 'never'.","commonSituations":"Configuring codexPermissionMode from a user default like 'on-request'; migrating an old run record whose stored approval policy predates the 'never' requirement; copying driver options from interactive Codex CLI usage into the runner backend.","solutions":["Set codexPermissionMode (approvalPolicy) to 'never' in the provider configuration before starting or recovering the run.","Remove the approvalPolicy field entirely to accept the backend default.","For recovery failures, correct the stored provider options in the run record, then retry recovery."],"exampleFix":"// before\n{ provider: { kind: \"codex\", approvalPolicy: \"on-request\" } }\n// after\n{ provider: { kind: \"codex\", approvalPolicy: \"never\" } }","handlingStrategy":"validation","validationCode":"if (provider.kind === \"codex\" && provider.approvalPolicy !== undefined && provider.approvalPolicy !== \"never\") {\n  throw new Error(`codexPermissionMode must be 'never', got '${provider.approvalPolicy}'`);\n}","typeGuard":"function codexPolicyIsValid(p) {\n  return p.kind !== \"codex\" || p.approvalPolicy === undefined || p.approvalPolicy === \"never\";\n}","tryCatchPattern":"try {\n  await backend.openSession(input);\n} catch (err) {\n  if (err.message.includes(\"codex_permission_mode_unqualified\")) {\n    console.error(\"Set codexPermissionMode to 'never' and restart the run\");\n    process.exit(1);\n  }\n  throw err;\n}","preventionTips":["Default codex provider configs to approvalPolicy 'never' for non-interactive runner contexts.","Validate provider options against the backend contract before persisting run records so recovery never inherits an invalid policy."],"tags":["configuration","codex","permission-mode"],"backgroundTag":"invalid-config-value","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"}