{"record":{"id":"d5a6b0ea50ebed32","repo":"JuliusBrussee/caveman","slug":"cave-sandbox-credential-missing","errorCode":"cave_sandbox_credential_missing","errorMessage":"cave_sandbox_credential_missing","messagePattern":"cave_sandbox_credential_missing","errorType":"error_code","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/agent/src/runtime.ts","lineNumber":624,"sourceCode":"    throw new Error(\"cave_sandbox_credential_capability_ambiguous\");\n  }\n}\n\n/** Build the complete environment for an isolated tool child. No spread of\n * `process.env`: only deterministic runtime baseline plus an exact provider\n * capability selected by the validated live profile. */\nexport function buildSandboxToolEnv(names: readonly string[] = []): NodeJS.ProcessEnv {\n  validateSandboxCredentialEnv(names);\n  const env: NodeJS.ProcessEnv = {\n    LANG: process.env.LANG ?? \"C\",\n    LC_ALL: process.env.LC_ALL ?? \"C\",\n    PATH: process.env.PATH ?? \"\",\n    TZ: process.env.TZ ?? \"UTC\",\n    CAVE_EVAL_FIXTURE: \"1\",\n  };\n  for (const name of names) {\n    const value = process.env[name];\n    if (value === undefined) throw new Error(\"cave_sandbox_credential_missing\");\n    env[name] = value;\n  }\n  return env;\n}\n\ninterface InternalRunOptions extends RunOptions {\n  lockedBuild?: CaveBuildLock;\n  candidatePlan?: CavePlan;\n  /**\n   * Resolved once per root run and handed to descendants so a nested agent\n   * neither re-probes the gateway nor disagrees with its parent about whether\n   * this run is optimized or observe-only.\n   */\n  caveRoute?: ResolvedCaveRoute;\n}\n\nexport type ResolvedCaveRoute = {\n  readonly useGateway: boolean;","sourceCodeStart":606,"sourceCodeEnd":642,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/3ee70a102609e550bd2e68004bf5990a9341c851/packages/agent/src/runtime.ts#L606-L642","documentation":"buildSandboxToolEnv injects the validated credential env vars into the child sandbox environment by reading them from process.env; if one is undefined the required live credential is absent and the build aborts.","triggerScenarios":"A sandbox profile allowlists a credential env var name but the corresponding variable is not set in the parent process environment when the sandboxed tool child is spawned.","commonSituations":"Running locally without exporting the provider API key that CI has; .env file not loaded before spawning the sandbox; a renamed credential env var; shell environment stripped (e.g. sudo, systemd, container with minimal env).","solutions":["Export the required provider credential env var before running the agent.","Load your .env file (e.g. dotenv) at process start.","Verify with `printenv ANTHROPIC_API_KEY` (or the relevant name) that it is set in the launching shell.","Ensure the same user/shell environment is used as where the profile was validated."],"exampleFix":"// before\nnode agent.mjs // OPENAI_API_KEY unset\n// after\nOPENAI_API_KEY=sk-... node agent.mjs","handlingStrategy":"validation","validationCode":"const missing = names.filter((n: string) => process.env[n] === undefined);\nif (missing.length) throw new Error(`missing credentials: ${missing.join(\",\")}`); // before spawning sandbox","typeGuard":null,"tryCatchPattern":"try {\n  const env = buildSandboxToolEnv(names);\n} catch (e) {\n  if (e.message === \"cave_sandbox_credential_missing\") {\n    console.error(\"Required provider credential env var is not set in this shell\");\n  } else throw e;\n}","preventionTips":["Export provider API keys before launching the agent.","Load .env at process startup (dotenv).","Pre-flight check all profile credential names with a startup assertion."],"tags":["sandbox","env","credentials","missing"],"backgroundTag":"missing-env-var","analyzedSha":"3ee70a102609e550bd2e68004bf5990a9341c851","analyzedAt":"2026-09-20T15:53:39.229Z","contentChangedAt":"2026-09-20T15:53:39.229Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}