JuliusBrussee/caveman · error · Error
cave_sandbox_credential_capability_ambiguous
cave_sandbox_credential_capability_ambiguous
Error message
cave_sandbox_credential_capability_ambiguous
What it means
validateSandboxCredentialEnv maps each requested credential env name to a provider capability; if the set of names spans more than one distinct capability, the request is ambiguous about which provider's credential to inject and is rejected.
Solutions
- Request credential env vars for exactly one provider capability per sandbox env.
- Split the sandbox tool run into separate runs per provider.
- Prune unneeded credential names from the profile.
- Verify the capability mapping by reading which env names map to which capability in the library.
Example fix
// before credentialEnv: ["ANTHROPIC_API_KEY", "OPENAI_API_KEY"]; // two capabilities // after credentialEnv: ["ANTHROPIC_API_KEY"];
Defensive patterns
Strategy: validation
Validate before calling
const caps = new Set(names.map((n: string) => SANDBOX_CREDENTIAL_ENV_TO_CAPABILITY.get(n)));
if (caps.size > 1) throw new Error("credential env spans multiple provider capabilities"); Type guard
const isSingleCapability = (names: string[]): boolean => new Set(names.map((n: string) => SANDBOX_CREDENTIAL_ENV_TO_CAPABILITY.get(n))).size <= 1;
Try / catch
try {
buildSandboxToolEnv(names);
} catch (e) {
if (e.message === "cave_sandbox_credential_capability_ambiguous") {
// split names by capability and run per provider
} else throw e;
} Prevention
- One provider's credentials per sandbox environment.
- Prune multi-provider leftovers from shared team profiles.
- Derive the credential list from the profile's provider field, not a hardcoded merged list.
When it happens
Trigger: A sandbox profile or buildSandboxToolEnv call requests credential env vars that map to two different provider capabilities (e.g. both an Anthropic key and an OpenAI key) in a single sandbox tool environment.
Common situations: Copy-pasting a profile and leaving credentials for two providers; merging profiles without pruning credential env lists; a shared team profile that accumulated multiple providers' keys.
Understand the failure class
Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.
Related errors
- cave_sandbox_credential_env_not_allowlisted
- cave_host_sandbox_nested_under_required
- cave_live_eval_sandbox_profile_escapes_root
- cave_sandbox_child_process_containment_unavailable
- cave_sandbox_conformance_failed
AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20).
Data as JSON: /api/errors/4b75038a9618005f.
Report an issue: GitHub.
Appendix: source
Thrown at packages/agent/src/runtime.ts:606
export function validateSandboxCredentialEnv(names: readonly string[]): void {
const capabilities = new Set<SandboxCredentialCapability>();
for (const name of names) {
const denied = typeof name === "string" &&
(SANDBOX_CREDENTIAL_DENY_NAMES.has(name) ||
SANDBOX_CREDENTIAL_DENY_PREFIXES.some((prefix) => name.startsWith(prefix)));
const capability = denied || typeof name !== "string"
? undefined
: SANDBOX_CREDENTIAL_ENV_TO_CAPABILITY.get(name);
if (capability === undefined) {
// Keep profile-controlled names out of errors. This is a policy result,
// not a diagnostic surface, and the name may itself identify a secret.
throw new Error("cave_sandbox_credential_env_not_allowlisted");
}
capabilities.add(capability);
}
if (capabilities.size > 1) {
throw new Error("cave_sandbox_credential_capability_ambiguous");
}
}
/** Build the complete environment for an isolated tool child. No spread of
* `process.env`: only deterministic runtime baseline plus an exact provider
* capability selected by the validated live profile. */
export function buildSandboxToolEnv(names: readonly string[] = []): NodeJS.ProcessEnv {
validateSandboxCredentialEnv(names);
const env: NodeJS.ProcessEnv = {
LANG: process.env.LANG ?? "C",
LC_ALL: process.env.LC_ALL ?? "C",
PATH: process.env.PATH ?? "",
TZ: process.env.TZ ?? "UTC",
CAVE_EVAL_FIXTURE: "1",
};
for (const name of names) {
const value = process.env[name];
if (value === undefined) throw new Error("cave_sandbox_credential_missing");View on GitHub (pinned to 3ee70a1026)