{"record":{"id":"4a9d3d7559976447","repo":"paperclipai/paperclip","slug":"daytona-can-delete-snapshot-templates-only-not","errorCode":null,"errorMessage":"Daytona can delete snapshot templates only, not ${templateKind}.","messagePattern":"Daytona can delete snapshot templates only, not (.+?)\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/plugins/sandbox-providers/daytona/src/plugin.ts","lineNumber":2344,"sourceCode":"        status: params.reason === \"timed_out\" ? \"timed_out\" : \"cancelled\",\n        metadata: {\n          provider: \"daytona\",\n          sandboxId: sandbox.id,\n          reason: params.reason ?? null,\n        },\n      };\n    } finally {\n      sandboxHandleTeardownGates.end(scope, teardownGate);\n      evictSandboxHandle(scope);\n    }\n  },\n\n  async onEnvironmentDeleteTemplate(\n    params: PluginEnvironmentDeleteTemplateParams,\n  ): Promise<PluginEnvironmentDeleteTemplateResult> {\n    const templateKind = params.templateKind ?? \"snapshot\";\n    if (templateKind !== \"snapshot\") {\n      throw new Error(`Daytona can delete snapshot templates only, not ${templateKind}.`);\n    }\n    const config = parseDriverConfig(params.config);\n    const client = createDaytonaClient(config) as Daytona & { snapshot?: DaytonaSnapshotService };\n    const snapshotService = client.snapshot;\n    if (typeof snapshotService?.get !== \"function\" || typeof snapshotService.delete !== \"function\") {\n      throw new Error(\"Daytona template deletion requires @daytonaio/sdk snapshot.get/delete support.\");\n    }\n    const snapshot = await snapshotService.get(params.templateRef);\n    await snapshotService.delete(snapshot);\n    return {\n      deleted: true,\n      metadata: {\n        provider: \"daytona\",\n        templateKind: \"snapshot\",\n        templateRefRedacted: true,\n        reason: params.reason ?? null,\n      },\n    };","sourceCodeStart":2326,"sourceCodeEnd":2362,"githubUrl":"https://github.com/paperclipai/paperclip/blob/67001ec6eb96ae601aa27bc91d9b2415d665334a/packages/plugins/sandbox-providers/daytona/src/plugin.ts#L2326-L2362","documentation":"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.","triggerScenarios":"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').","commonSituations":"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.","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."],"exampleFix":"// before\nawait plugin.onEnvironmentDeleteTemplate({\n  ...params,\n  templateKind: 'image',\n});\n\n// after\nawait plugin.onEnvironmentDeleteTemplate({\n  ...params,\n  templateKind: 'snapshot',\n});","handlingStrategy":"validation","validationCode":"function assertSnapshotKind(templateKind: string | undefined): void {\n  const kind = templateKind ?? 'snapshot';\n  if (kind !== 'snapshot') {\n    throw new Error(\n      `Daytona delete-template requires templateKind 'snapshot', got '${kind}'`,\n    );\n  }\n}\n// call before plugin.onEnvironmentDeleteTemplate(...)","typeGuard":"function isSnapshotKind(k: unknown): k is 'snapshot' | undefined {\n  return k === undefined || k === 'snapshot';\n}","tryCatchPattern":"try {\n  await plugin.onEnvironmentDeleteTemplate(params);\n} catch (err) {\n  if (err instanceof Error && /snapshot templates only/.test(err.message)) {\n    // route to a provider that supports this kind, or no-op\n    return { deleted: false };\n  }\n  throw err;\n}","preventionTips":["Normalize templateKind to 'snapshot' at the caller boundary for the daytona driver.","Keep provider-agnostic dispatch tables that map each provider's supported kinds."],"tags":["daytona","template","input-validation","delete-template"],"backgroundTag":null,"analyzedSha":"67001ec6eb96ae601aa27bc91d9b2415d665334a","analyzedAt":"2026-08-12T12:05:45.408Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}