Skip to content

Commit 267c534

Browse files
author
John Donmoyer
committed
fix: improve error handling and comment accuracy in quickstart
- Stop spinner on volume/sandbox creation failures for clean output - Include orphaned volume cleanup instructions when sandbox boot fails - Track failed setup commands and warn that snapshot will be incomplete - Fix misleading "temporary volume" comments (volume is kept permanently)
1 parent 15c1773 commit 267c534

1 file changed

Lines changed: 43 additions & 18 deletions

File tree

sandbox/quickstart.ts

Lines changed: 43 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -225,8 +225,9 @@ function promptSnapshotName(): string | null {
225225
}
226226

227227
// --- Build Logic ---
228-
// This is the core of the feature. It creates a temporary volume,
229-
// boots a sandbox, installs everything, then snapshots the result.
228+
// This is the core of the feature. It creates a volume, boots a
229+
// sandbox, installs everything, then snapshots the result.
230+
// The volume is kept because the snapshot depends on it.
230231

231232
async function buildSnapshot(
232233
client: Client,
@@ -241,7 +242,7 @@ async function buildSnapshot(
241242
verbose: boolean;
242243
},
243244
): Promise<void> {
244-
// A unique name for the temporary volume so it doesn't clash with anything
245+
// A unique name for the build volume so it doesn't clash with anything
245246
const volumeSlug = `qs-temp-${Date.now()}`;
246247

247248
// In verbose mode, command output goes straight to the terminal.
@@ -268,29 +269,44 @@ async function buildSnapshot(
268269
return `[${currentStep}/${totalSteps}] ${label}`;
269270
};
270271

271-
// Step 1: Create a temporary volume based on Debian 13
272-
spinner.message = "Creating temporary volume...";
272+
spinner.message = "Creating volume...";
273273
spinner.start();
274-
const volume = await client.volumes.create({
275-
slug: volumeSlug,
276-
capacity: options.capacity,
277-
region: options.region,
278-
from: "builtin:debian-13",
279-
});
274+
let volume;
275+
try {
276+
volume = await client.volumes.create({
277+
slug: volumeSlug,
278+
capacity: options.capacity,
279+
region: options.region,
280+
from: "builtin:debian-13",
281+
});
282+
} catch (e) {
283+
spinner.stop();
284+
throw new Error(`Failed to create volume: ${e}`);
285+
}
280286
spinner.stop();
281287
console.log(`${green("✔")} Volume created`);
282288

283289
// Boot a sandbox using this volume as its root filesystem.
284290
// The sandbox is short-lived (10m timeout) — just long enough to install.
285291
spinner.message = "Booting sandbox...";
286292
spinner.start();
287-
const sandbox = await Sandbox.create({
288-
token: options.token,
289-
org: options.org,
290-
timeout: "10m",
291-
region: options.region,
292-
root: volume.id,
293-
});
293+
let sandbox;
294+
try {
295+
sandbox = await Sandbox.create({
296+
token: options.token,
297+
org: options.org,
298+
timeout: "10m",
299+
region: options.region,
300+
root: volume.id,
301+
});
302+
} catch (e) {
303+
spinner.stop();
304+
throw new Error(
305+
`Failed to boot sandbox: ${e}\n` +
306+
` Volume '${volumeSlug}' was created but is now unused.\n` +
307+
` You can delete it with: deno sandbox volumes delete ${volumeSlug}`,
308+
);
309+
}
294310
spinner.stop();
295311
console.log(`${green("✔")} Sandbox booted`);
296312

@@ -330,17 +346,26 @@ async function buildSnapshot(
330346
}
331347

332348
// Setup commands are optional — if one fails we warn but keep going
349+
const failedCommands: string[] = [];
333350
for (const cmd of options.setupCommands) {
334351
spinner.message = step(`Running: ${cmd}`);
335352
spinner.start();
336353
const setupOk = await runInSandbox(sandbox, cmd);
337354
spinner.stop();
338355
if (!setupOk) {
339356
console.log(`${yellow("⚠")} Setup command failed: ${cmd}`);
357+
failedCommands.push(cmd);
340358
} else {
341359
console.log(`${green("✔")} ${cmd}`);
342360
}
343361
}
362+
if (failedCommands.length > 0) {
363+
console.log();
364+
console.log(
365+
`${yellow("⚠")} ${failedCommands.length} setup command(s) failed. ` +
366+
"The snapshot will be incomplete.",
367+
);
368+
}
344369
} finally {
345370
// We use kill() instead of close() because close() only disconnects
346371
// the client while the sandbox continues running server-side with

0 commit comments

Comments
 (0)