paperclipai/paperclip · error · Error
exe.dev environments require an API key in config or EXE_API
Error message
exe.dev environments require an API key in config or EXE_API_KEY.
What it means
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.
Source
Thrown at packages/plugins/sandbox-providers/exe-dev/src/plugin.ts:272
integrations: parseStringArray(raw.integrations),
tags: parseStringArray(raw.tags),
setupScript: parseOptionalString(raw.setupScript),
prompt: parseOptionalString(raw.prompt),
timeoutMs: Number.isFinite(timeoutMs) ? Math.trunc(timeoutMs) : DEFAULT_TIMEOUT_MS,
reuseLease: raw.reuseLease === true,
sshUser: parseOptionalString(raw.sshUser),
sshPrivateKey: parseOptionalString(raw.sshPrivateKey),
sshIdentityFile: parseOptionalString(raw.sshIdentityFile),
sshPort: Number.isFinite(sshPort) ? Math.trunc(sshPort) : 22,
strictHostKeyChecking: parseOptionalString(raw.strictHostKeyChecking) ?? "accept-new",
};
}
function resolveApiKey(config: ExeDevDriverConfig): string {
if (config.apiKey) return config.apiKey;
const envApiKey = process.env.EXE_API_KEY?.trim() ?? "";
if (!envApiKey) {
throw new Error("exe.dev environments require an API key in config or EXE_API_KEY.");
}
return envApiKey;
}
function isValidShellEnvKey(value: string): boolean {
return /^[A-Za-z_][A-Za-z0-9_]*$/.test(value);
}
function shellQuote(value: string): string {
return `'${value.replace(/'/g, `'"'"'`)}'`;
}
function formatErrorMessage(error: unknown): string {
return error instanceof Error ? error.message : String(error);
}
function buildVmName(config: ExeDevDriverConfig, params: PluginEnvironmentAcquireLeaseParams): string {
const envPart = params.environmentId.replace(/[^a-z0-9]+/gi, "").slice(0, 8).toLowerCase() || "env";View on GitHub (pinned to 67001ec6eb)
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.
Example fix
# before
export EXEDEV_API_KEY=... # wrong name
# after
export EXE_API_KEY=... # correct name
# or in driver config:
# { "apiKey": "...", "apiUrl": "https://api.exe.dev/command" } Defensive patterns
Strategy: validation
Validate before calling
function ensureExeKey(config: { apiKey?: string | null }): string {
const fromEnv = process.env.EXE_API_KEY?.trim() ?? '';
const key = (config.apiKey && config.apiKey.trim()) || fromEnv;
if (!key) throw new Error('EXE_API_KEY (or config.apiKey) must be set');
return key;
} Type guard
function hasExeKey(config: { apiKey?: string | null }): boolean {
return Boolean((config.apiKey && config.apiKey.trim()) || (process.env.EXE_API_KEY && process.env.EXE_API_KEY.trim()));
} Try / catch
try {
await plugin.onEnvironmentProbe(params);
} catch (err) {
if (err instanceof Error && /EXE_API_KEY/.test(err.message)) {
return { ok: false, error: 'exe.dev API key not configured' };
}
throw err;
} Prevention
- Use the exact env var name EXE_API_KEY (not EXEDEV_API_KEY).
- Boot-time validate that exe.dev environments have a resolvable key.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- E2B sandbox environments require an API key in config or E2B
- Daytona sandbox environments require an API key in config or
- exe.dev API command failed (${response.status}) for: ${logCo
- Request failed: ${response.status}
- CLI auth challenge was cancelled.
AI-assisted analysis of paperclipai/paperclip@67001ec6eb (2026-08-12).
Data as JSON: /api/errors/2bf668dc08287544.
Report an issue: GitHub.