paperclipai/paperclip · error · Error
Daytona can delete snapshot templates only, not ${templateKi
Error message
Daytona can delete snapshot templates only, not ${templateKind}. What it means
Thrown by onEnvironmentDeleteTemplate after it defaults params.templateKind to 'snapshot'. Daytona only models templates as snapshots, so any other templateKind value (e.g. 'image', 'ami', 'vm') is rejected before any SDK call is made. This is an input-contract guard, not an SDK capability check.
Source
Thrown at packages/plugins/sandbox-providers/daytona/src/plugin.ts:2344
status: params.reason === "timed_out" ? "timed_out" : "cancelled",
metadata: {
provider: "daytona",
sandboxId: sandbox.id,
reason: params.reason ?? null,
},
};
} finally {
sandboxHandleTeardownGates.end(scope, teardownGate);
evictSandboxHandle(scope);
}
},
async onEnvironmentDeleteTemplate(
params: PluginEnvironmentDeleteTemplateParams,
): Promise<PluginEnvironmentDeleteTemplateResult> {
const templateKind = params.templateKind ?? "snapshot";
if (templateKind !== "snapshot") {
throw new Error(`Daytona can delete snapshot templates only, not ${templateKind}.`);
}
const config = parseDriverConfig(params.config);
const client = createDaytonaClient(config) as Daytona & { snapshot?: DaytonaSnapshotService };
const snapshotService = client.snapshot;
if (typeof snapshotService?.get !== "function" || typeof snapshotService.delete !== "function") {
throw new Error("Daytona template deletion requires @daytonaio/sdk snapshot.get/delete support.");
}
const snapshot = await snapshotService.get(params.templateRef);
await snapshotService.delete(snapshot);
return {
deleted: true,
metadata: {
provider: "daytona",
templateKind: "snapshot",
templateRefRedacted: true,
reason: params.reason ?? null,
},
};View on GitHub (pinned to 67001ec6eb)
Solutions
- Omit templateKind (it defaults to 'snapshot') or explicitly pass templateKind: 'snapshot' when calling Daytona delete-template.
- If your caller is provider-agnostic, map the kind to 'snapshot' for the daytona driver before dispatching.
- Do not issue delete-template for non-snapshot kinds on Daytona; route image/AMI teardown to a provider that supports them.
Example fix
// before
await plugin.onEnvironmentDeleteTemplate({
...params,
templateKind: 'image',
});
// after
await plugin.onEnvironmentDeleteTemplate({
...params,
templateKind: 'snapshot',
}); Defensive patterns
Strategy: validation
Validate before calling
function assertSnapshotKind(templateKind: string | undefined): void {
const kind = templateKind ?? 'snapshot';
if (kind !== 'snapshot') {
throw new Error(
`Daytona delete-template requires templateKind 'snapshot', got '${kind}'`,
);
}
}
// call before plugin.onEnvironmentDeleteTemplate(...) Type guard
function isSnapshotKind(k: unknown): k is 'snapshot' | undefined {
return k === undefined || k === 'snapshot';
} Try / catch
try {
await plugin.onEnvironmentDeleteTemplate(params);
} catch (err) {
if (err instanceof Error && /snapshot templates only/.test(err.message)) {
// route to a provider that supports this kind, or no-op
return { deleted: false };
}
throw err;
} Prevention
- Normalize templateKind to 'snapshot' at the caller boundary for the daytona driver.
- Keep provider-agnostic dispatch tables that map each provider's supported kinds.
When it happens
Trigger: Issuing a delete-template call to the Daytona provider with params.templateKind set to anything other than 'snapshot' (or relying on a caller that sends a provider-agnostic kind like 'image').
Common situations: A control-plane layer that picks templateKind from a generic catalog forwards a non-snapshot kind to Daytona; a config/seed file copied from another provider (e.g. an AMI-based one) without translating templateKind.
Related errors
- Daytona interactive setup can start from image or snapshot t
- Daytona template capture requires @daytonaio/sdk Sandbox._ex
- Daytona template deletion requires @daytonaio/sdk snapshot.g
- Daytona syncIn requires a provider lease ID.
- Daytona syncOut requires a provider lease ID.
AI-assisted analysis of paperclipai/paperclip@67001ec6eb (2026-08-12).
Data as JSON: /api/errors/4a9d3d7559976447.
Report an issue: GitHub.