{"record":{"id":"1f6b5235dde0a173","repo":"windmill-labs/windmill","slug":"draft-diff-not-supported-for-kind-kind","errorCode":null,"errorMessage":"Draft diff not supported for kind ${kind}","messagePattern":"Draft diff not supported for kind (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"frontend/src/lib/utils_draft_deploy.ts","lineNumber":345,"sourceCode":"\t\treturn {\n\t\t\tdeployed: draftOnly ? EMPTY_DEPLOYED.app!(undefined) : deployed,\n\t\t\tdraft: {\n\t\t\t\tsummary: draftParts.summary ?? r.summary ?? '',\n\t\t\t\tvalue: draftParts.value,\n\t\t\t\tpath: draftParts.draftPath ?? r.path\n\t\t\t},\n\t\t\thasDraft: r.draft != null,\n\t\t\tnoDeployed: r.no_deployed === true\n\t\t}\n\t} else {\n\t\t// Variables / resources / schedules / triggers: one overlay GET yields\n\t\t// both sides, but the draft side is the editor's state shape while the\n\t\t// deployed side is the backend row — they diverge enough to make a raw\n\t\t// diff pure noise. Canonicalize both onto a shared field set (same shaping\n\t\t// the compare page's `getItemValue` applies) so only real changes show.\n\t\tconst getter = OVERLAY_GETTERS[kind]\n\t\tif (!getter) {\n\t\t\tthrow new Error(`Draft diff not supported for kind ${kind}`)\n\t\t}\n\t\tconst { deployed, draft, hasDraft, noDeployed } = splitOverlay(await getter(workspace, path))\n\t\treturn {\n\t\t\tdeployed: draftOnly ? {} : canonicalizeDraftDiffValue(kind, deployed, false),\n\t\t\tdraft: canonicalizeDraftDiffValue(kind, draft, true),\n\t\t\thasDraft,\n\t\t\tnoDeployed\n\t\t}\n\t}\n}\n\n/**\n * Whether a draft's base is stale: the deployed version the draft forked from\n * no longer matches the current deployed head — a newer version was deployed\n * after the draft began, so deploying the draft would silently revert it.\n * Scripts compare the draft's `parent_hash` vs the deployed `hash`; flows the\n * pinned `version_id` vs the deployed head `version_id`; apps (incl. raw) the\n * pinned `parent_version` vs the head of `versions`. `r` is the item fetched","sourceCodeStart":327,"sourceCodeEnd":363,"githubUrl":"https://github.com/windmill-labs/windmill/blob/e474e8803ce2ff5c2df09a58dab51d45f5c922ca/frontend/src/lib/utils_draft_deploy.ts#L327-L363","documentation":"getDraftDiffValues in frontend/src/lib/utils_draft_deploy.ts (line 345) computes a deployed-vs-draft diff by looking up a getter in the OVERLAY_GETTERS map keyed by item kind, then canonicalizing both sides onto a shared field set. When the kind has no entry in OVERLAY_GETTERS (the map has no draft overlay representation for it), the code throws 'Draft diff not supported for kind ...'. Unlike the trigger dispatchers, this one intentionally guards against kinds whose draft shapes are too divergent to diff meaningfully.","triggerScenarios":"Calling getDraftDiffValues (via values, diffWorkspaceItem, or the {deployed,draft} overloads) with a kind that has no OVERLAY_GETTERS entry — e.g. raw_app, folder, resource_type, datatable_migration, or a new item kind added to the Kind union without a draft-diff getter.","commonSituations":"Trying to show a diff drawer for a newly supported deployable kind before adding its overlay getter; a kind renamed in the Kind union while the OVERLAY_GETTERS map still uses the old key; users hitting it on draft bundles like data_pipeline that are not diffable.","solutions":["Check the `kind` in the error and confirm it should be diffable; if it is (e.g. a recently added kind), add an entry to OVERLAY_GETTERS returning { deployed, draft } for that kind.","If the kind is not diffable by design, hide the diff action in the UI (guard with `kind in OVERLAY_GETTERS`) instead of invoking getDraftDiffValues.","Update canonicalizeDraftDiffValue with a shaping branch for the new kind so the diff output is not raw noise.","Ensure kind keys are in sync between the Kind union and OVERLAY_GETTERS after any rename."],"exampleFix":"// before\nconst diff = await getDraftDiffValues('raw_app', workspace, path)\n// after\nif (kind in OVERLAY_GETTERS) {\n  const diff = await getDraftDiffValues(kind, workspace, path)\n} else {\n  // hide the diff entry for this kind in the UI\n}","handlingStrategy":"type-guard","validationCode":"import { OVERLAY_GETTERS } from '$lib/utils_draft_deploy'\nfunction canDiffDraft(kind: Kind): kind is keyof typeof OVERLAY_GETTERS {\n  return kind in OVERLAY_GETTERS\n}","typeGuard":"const OVERLAY_GETTERS = { script: getScriptOverlay, flow: getFlowOverlay /* ... */ } as const\ntype DiffableKind = keyof typeof OVERLAY_GETTERS\nfunction isDiffableKind(k: Kind): k is DiffableKind {\n  return k in OVERLAY_GETTERS\n}","tryCatchPattern":"try {\n  const diff = await getDraftDiffValues(kind, workspace, path)\n} catch (e) {\n  if (String(e?.message).startsWith('Draft diff not supported for kind')) {\n    // fall back to the plain deploy view without a diff drawer\n  } else throw e\n}","preventionTips":["Gate the diff UI action on `kind in OVERLAY_GETTERS` so unsupported kinds never reach the throw.","When adding a new Kind member, add its OVERLAY_GETTERS entry and canonicalizeDraftDiffValue branch in the same change.","Derive the diffable-kind list from OVERLAY_GETTERS' keys (a satisfies/typeof check) so renames fail at compile time instead of runtime."],"tags":["frontend","typescript","draft","diff","unsupported-kind"],"backgroundTag":"unsupported-trigger-kind","analyzedSha":"e474e8803ce2ff5c2df09a58dab51d45f5c922ca","analyzedAt":"2026-09-03T12:38:19.024Z","contentChangedAt":"2026-09-03T12:38:19.024Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}