{"record":{"id":"222526aa49e42d58","repo":"paperclipai/paperclip","slug":"e2b-sandbox-environments-require-an-api-key-in-con","errorCode":null,"errorMessage":"E2B sandbox environments require an API key in config or E2B_API_KEY.","messagePattern":"E2B sandbox environments require an API key in config or E2B_API_KEY\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/plugins/sandbox-providers/e2b/src/plugin.ts","lineNumber":52,"sourceCode":"  const template = typeof raw.template === \"string\" && raw.template.trim().length > 0\n    ? raw.template.trim()\n    : \"base\";\n  const timeoutMs = Number(raw.timeoutMs ?? 3_600_000);\n  return {\n    template,\n    apiKey: typeof raw.apiKey === \"string\" && raw.apiKey.trim().length > 0 ? raw.apiKey.trim() : null,\n    timeoutMs: Number.isFinite(timeoutMs) ? Math.trunc(timeoutMs) : 3_600_000,\n    reuseLease: raw.reuseLease === true,\n  };\n}\n\nfunction resolveApiKey(config: E2bDriverConfig): string {\n  if (config.apiKey) {\n    return config.apiKey;\n  }\n  const envApiKey = process.env.E2B_API_KEY?.trim() ?? \"\";\n  if (!envApiKey) {\n    throw new Error(\"E2B sandbox environments require an API key in config or E2B_API_KEY.\");\n  }\n  return envApiKey;\n}\n\nasync function createSandbox(config: E2bDriverConfig): Promise<Sandbox> {\n  const options = {\n    apiKey: resolveApiKey(config),\n    timeoutMs: config.timeoutMs,\n    metadata: {\n      paperclipProvider: \"e2b\",\n    },\n  };\n  return await Sandbox.create(config.template, options);\n}\n\nfunction formatErrorMessage(error: unknown): string {\n  return error instanceof Error ? error.message : String(error);\n}","sourceCodeStart":34,"sourceCodeEnd":70,"githubUrl":"https://github.com/paperclipai/paperclip/blob/67001ec6eb96ae601aa27bc91d9b2415d665334a/packages/plugins/sandbox-providers/e2b/src/plugin.ts#L34-L70","documentation":"Thrown by resolveApiKey in the E2B provider when neither the driver config's apiKey field nor the E2B_API_KEY environment variable yields a non-empty string. resolveApiKey is called by createSandbox on every Sandbox.create, so the error surfaces on any lease/probe operation that needs to spin up an E2B sandbox.","triggerScenarios":"Any E2B provider call (probe, acquireLease, realizeWorkspace) invoked with config.apiKey unset/blank AND process.env.E2B_API_KEY unset/blank/whitespace-only. parseDriverConfig trims and nulls blank apiKeys, so a whitespace-only config value also falls through to the env lookup.","commonSituations":"Fresh dev/CI environment where E2B_API_KEY was never exported; .env file not loaded by the worker process; key redacted to empty by a secret manager; config propagated from a template that omitted apiKey.","solutions":["Export E2B_API_KEY in the worker environment (export E2B_API_KEY=...) or add it to the loaded .env.","Pass apiKey explicitly in the E2B driver config blob stored for the environment.","Verify the value is non-empty after trim and that the process actually has the env var (print process.env.E2B_API_KEY?.length, never the value)."],"exampleFix":"# before\n# (nothing set)\n\n# after\nexport E2B_API_KEY=e2b_********************\n# or in driver config:\n# { \"apiKey\": \"e2b_...\", \"template\": \"base\" }","handlingStrategy":"validation","validationCode":"function ensureE2bKey(config: { apiKey?: string | null }): string {\n  const fromEnv = process.env.E2B_API_KEY?.trim() ?? '';\n  const key = (config.apiKey && config.apiKey.trim()) || fromEnv;\n  if (!key) throw new Error('E2B_API_KEY (or config.apiKey) must be set');\n  return key;\n}","typeGuard":"function hasE2bKey(config: { apiKey?: string | null }): boolean {\n  return Boolean((config.apiKey && config.apiKey.trim()) || (process.env.E2B_API_KEY && process.env.E2B_API_KEY.trim()));\n}","tryCatchPattern":"try {\n  await plugin.onEnvironmentProbe(params);\n} catch (err) {\n  if (err instanceof Error && /E2B_API_KEY/.test(err.message)) {\n    return { ok: false, error: 'E2B API key not configured' };\n  }\n  throw err;\n}","preventionTips":["Add a boot-time config check that fails the worker fast when E2B is configured but the key is missing.","Keep the key in a secret manager and inject via env; never log the value."],"tags":["e2b","config","api-key","env-var","sandbox","auth"],"backgroundTag":null,"analyzedSha":"67001ec6eb96ae601aa27bc91d9b2415d665334a","analyzedAt":"2026-08-12T12:05:45.408Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}