{"record":{"id":"2bf668dc08287544","repo":"paperclipai/paperclip","slug":"exe-dev-environments-require-an-api-key-in-config","errorCode":null,"errorMessage":"exe.dev environments require an API key in config or EXE_API_KEY.","messagePattern":"exe\\.dev environments require an API key in config or EXE_API_KEY\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/plugins/sandbox-providers/exe-dev/src/plugin.ts","lineNumber":272,"sourceCode":"    integrations: parseStringArray(raw.integrations),\n    tags: parseStringArray(raw.tags),\n    setupScript: parseOptionalString(raw.setupScript),\n    prompt: parseOptionalString(raw.prompt),\n    timeoutMs: Number.isFinite(timeoutMs) ? Math.trunc(timeoutMs) : DEFAULT_TIMEOUT_MS,\n    reuseLease: raw.reuseLease === true,\n    sshUser: parseOptionalString(raw.sshUser),\n    sshPrivateKey: parseOptionalString(raw.sshPrivateKey),\n    sshIdentityFile: parseOptionalString(raw.sshIdentityFile),\n    sshPort: Number.isFinite(sshPort) ? Math.trunc(sshPort) : 22,\n    strictHostKeyChecking: parseOptionalString(raw.strictHostKeyChecking) ?? \"accept-new\",\n  };\n}\n\nfunction resolveApiKey(config: ExeDevDriverConfig): string {\n  if (config.apiKey) return config.apiKey;\n  const envApiKey = process.env.EXE_API_KEY?.trim() ?? \"\";\n  if (!envApiKey) {\n    throw new Error(\"exe.dev environments require an API key in config or EXE_API_KEY.\");\n  }\n  return envApiKey;\n}\n\nfunction isValidShellEnvKey(value: string): boolean {\n  return /^[A-Za-z_][A-Za-z0-9_]*$/.test(value);\n}\n\nfunction shellQuote(value: string): string {\n  return `'${value.replace(/'/g, `'\"'\"'`)}'`;\n}\n\nfunction formatErrorMessage(error: unknown): string {\n  return error instanceof Error ? error.message : String(error);\n}\n\nfunction buildVmName(config: ExeDevDriverConfig, params: PluginEnvironmentAcquireLeaseParams): string {\n  const envPart = params.environmentId.replace(/[^a-z0-9]+/gi, \"\").slice(0, 8).toLowerCase() || \"env\";","sourceCodeStart":254,"sourceCodeEnd":290,"githubUrl":"https://github.com/paperclipai/paperclip/blob/67001ec6eb96ae601aa27bc91d9b2415d665334a/packages/plugins/sandbox-providers/exe-dev/src/plugin.ts#L254-L290","documentation":"Thrown by resolveApiKey in the exe.dev provider when neither config.apiKey nor process.env.EXE_API_KEY yields a non-empty string. resolveApiKey is called inside runLifecycleCommand on every POST to the exe.dev API (Authorization: Bearer <key>), so the error surfaces on any lease/probe/lifecycle call.","triggerScenarios":"Any exe.dev provider operation invoked with config.apiKey unset/blank (parseOptionalString nulls blank values) AND process.env.EXE_API_KEY unset/blank/whitespace-only.","commonSituations":"Worker deployed without EXE_API_KEY in its env; secret injected under a different name (e.g. EXEDEV_API_KEY); config block for exe.dev missing the apiKey field; CI run that never sourced the secrets file.","solutions":["Export EXE_API_KEY (note: EXE_API_KEY, not EXEDEV_API_KEY) in the worker environment.","Set apiKey in the exe.dev driver config blob.","Confirm the variable name and that the value survives trim; check the secret mount in the deployment."],"exampleFix":"# before\nexport EXEDEV_API_KEY=...   # wrong name\n\n# after\nexport EXE_API_KEY=...       # correct name\n# or in driver config:\n# { \"apiKey\": \"...\", \"apiUrl\": \"https://api.exe.dev/command\" }","handlingStrategy":"validation","validationCode":"function ensureExeKey(config: { apiKey?: string | null }): string {\n  const fromEnv = process.env.EXE_API_KEY?.trim() ?? '';\n  const key = (config.apiKey && config.apiKey.trim()) || fromEnv;\n  if (!key) throw new Error('EXE_API_KEY (or config.apiKey) must be set');\n  return key;\n}","typeGuard":"function hasExeKey(config: { apiKey?: string | null }): boolean {\n  return Boolean((config.apiKey && config.apiKey.trim()) || (process.env.EXE_API_KEY && process.env.EXE_API_KEY.trim()));\n}","tryCatchPattern":"try {\n  await plugin.onEnvironmentProbe(params);\n} catch (err) {\n  if (err instanceof Error && /EXE_API_KEY/.test(err.message)) {\n    return { ok: false, error: 'exe.dev API key not configured' };\n  }\n  throw err;\n}","preventionTips":["Use the exact env var name EXE_API_KEY (not EXEDEV_API_KEY).","Boot-time validate that exe.dev environments have a resolvable key."],"tags":["exe-dev","config","api-key","env-var","auth"],"backgroundTag":null,"analyzedSha":"67001ec6eb96ae601aa27bc91d9b2415d665334a","analyzedAt":"2026-08-12T12:05:45.408Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}