fix(exe-dev): translate SSH 'invalid format' stderr into actionable key-format message (PAPA-450)

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
Devin FoleyandPaperclip committed 2026-05-29 17:22:32 -07:00
1 parent 980bfc7301
commit c1ae76c6e5
2 files changed
+40

No files matched your search

@@ -346,6 +346,38 @@ describe("exe.dev sandbox provider plugin", () => {
expect(String(fetchMock.mock.calls[1]?.[1]?.body ?? "")).toBe("rm --json 'paperclip-env-run'");
});
it("surfaces invalid SSH key-format guidance during lease acquisition", async () => {
fetchMock.mockResolvedValueOnce(
new Response(JSON.stringify({
vm_name: "paperclip-env-run",
ssh_dest: "paperclip-env-run.exe.xyz",
https_url: "https://paperclip-env-run.exe.xyz",
status: "running",
}), { status: 200 }),
);
fetchMock.mockResolvedValueOnce(new Response("{}", { status: 200 }));
queueSpawnResult({
code: 255,
stderr: 'Load key "/tmp/paperclip-exe-dev-ssh-abc/id_ed25519": invalid format\n',
});
await expect(plugin.definition.onEnvironmentAcquireLease?.({
driverKey: "exe-dev",
companyId: "company-1",
environmentId: "env-1",
runId: "run-1",
config: {
apiKey: "api-key",
sshPrivateKey: "not-actually-a-key",
timeoutMs: 300000,
},
})).rejects.toThrow(
"the configured SSH private key isn't an OpenSSH-format private key",
);
expect(String(fetchMock.mock.calls[1]?.[1]?.body ?? "")).toBe("rm --json 'paperclip-env-run'");
});
it("redacts sensitive lifecycle flags in API errors", async () => {
fetchMock.mockResolvedValueOnce(new Response("upstream boom", { status: 500 }));
@@ -68,6 +68,7 @@ const SSH_SIGKILL_GRACE_MS = 250;
const MAX_VM_RECORD_DEPTH = 4;
const EXE_DEV_SSH_ONBOARDING_MARKER = "Please complete registration by running: ssh exe.dev";
const EXE_DEV_SSH_EMAIL_PROMPT = "Please enter your email address:";
const EXE_DEV_SSH_INVALID_KEY_FORMAT = /Load key [^\n]*invalid format/i;
// exe.dev's `--setup-script` runs at VM init as the unprivileged `exedev` user, which
// has passwordless sudo. The Paperclip sandbox callback bridge is a Node script, so
@@ -498,6 +499,13 @@ function formatSshFailure(
].join(" ");
}
if (EXE_DEV_SSH_INVALID_KEY_FORMAT.test(combinedOutput)) {
return [
`Failed to ${action} exe.dev VM ${vmName}: the configured SSH private key isn't an OpenSSH-format private key.`,
"Confirm the secret starts with `-----BEGIN … PRIVATE KEY-----` and isn't the `.pub` file or a PuTTY `.ppk` export.",
].join(" ");
}
return `Failed to ${action} exe.dev VM ${vmName}: ${result.stderr.trim() || result.stdout.trim() || "unknown error"}`;
}