paperclipai/paperclip · error · ExeDevApiError
exe.dev API command failed
Error message
exe.dev API command failed (${response.status}) for: ${logCommand} What it means
HTTP failure surfacing in runLifecycleCommand: the POST to the exe.dev API endpoint returned a non-ok status (status code in message) for the named (possibly redacted) lifecycle command. Response body text was parsed and attached as error detail; wrapped as ExeDevApiError so callers can distinguish exe.dev API failures from local ones.
Solutions
- Check the exe.dev CLI output and credentials; fix the failing command and retry.
Defensive patterns
Strategy: validation
When it happens
Trigger: Thrown at packages/plugins/sandbox-providers/exe-dev/src/plugin.ts:388 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of paperclipai/paperclip@a7e689b3c3 (2026-08-18).
Data as JSON: /api/errors/f432e6665b660e7f.
Report an issue: GitHub.
Appendix: source
Thrown at packages/plugins/sandbox-providers/exe-dev/src/plugin.ts:390
}
async function runLifecycleCommand(
config: ExeDevDriverConfig,
command: string,
logCommand = command,
): Promise<unknown> {
const response = await fetch(config.apiUrl, {
method: "POST",
headers: {
Authorization: `Bearer ${resolveApiKey(config)}`,
"Content-Type": "text/plain; charset=utf-8",
},
body: command,
signal: AbortSignal.timeout(Math.min(config.timeoutMs, EXE_DEV_API_MAX_TIMEOUT_MS)),
});
const body = await response.text();
if (!response.ok) {
throw new ExeDevApiError(
`exe.dev API command failed (${response.status}) for: ${logCommand}`,
response.status,
body,
);
}
const trimmed = body.trim();
if (!trimmed) return null;
try {
return JSON.parse(trimmed);
} catch {
return body;
}
}
function parseVmRecord(value: unknown, depth = 0): ExeDevVmRecord | null {
if (depth > MAX_VM_RECORD_DEPTH) return null;
if (!value || typeof value !== "object" || Array.isArray(value)) return null;View on GitHub (pinned to a7e689b3c3)