windmill-labs/windmill · error
Draft app "${path}" has no policy to deploy.
Error message
Draft app "${path}" has no policy to deploy. What it means
Thrown while deploying a raw app draft in the chat's deployDraft tool. Before deploying, the tool recomputes the app's policy (recomputeAppPolicy) from its runnables and data; if the resulting appValue.policy is falsy, there is no permission policy to ship, and deploying would leave the app without access rules. The tool aborts and asks for a draft with a computed policy.
Source
Thrown at frontend/src/lib/components/copilot/chat/global/core.ts:7415
: undefined
assertDraftBasedOnLatest(
'app',
path,
draft.parentVersionId,
deployedApp?.versions?.[deployedApp.versions.length - 1],
force
)
}
const appValue: AppDraftValue = {
...appDraft,
files: { ...(appDraft.files ?? {}) },
runnables: { ...(appDraft.runnables ?? {}) },
data: appDraft.data ?? { ...DEFAULT_RAW_APP_DATA }
}
await recomputeAppPolicy(appValue)
const policy = appValue.policy
if (!policy) {
throw new Error(`Draft app "${path}" has no policy to deploy.`)
}
// An app deployed on its own while a path runnable still points at a draft
// is deployed and broken — the deploy has to say so, not just report success.
const undeployedTargets = await undeployedRunnableTargets(workspace, appValue.runnables)
if (undeployedTargets.length > 0) {
deployNote =
`These backend runnables point at items that are NOT deployed, so they fail at runtime: ` +
`${undeployedTargets.join(', ')}. Deploy those items too, and tell the user the app is ` +
`not working until they are.`
}
toolCallbacks.setToolStatus(toolId, {
content: `Bundling app "${path}"...`
})
const bundle = await bundleRawAppDraft({
workspace,
files: appValue.files,View on GitHub (pinned to e474e8803c)
Solutions
- Open the raw app draft and ensure its runnables/data are well-formed so a policy can be computed, then redeploy.
- Check the draft against DEFAULT_RAW_APP_DATA to spot missing fields the policy derivation relies on.
- If recomputation is failing on valid data, investigate recomputeAppPolicy / rawAppPolicy for a regression.
Example fix
// before: draft.data missing expected sections
await deployDraft({ type: 'raw_app', path: 'a/admin_panel' })
// Error: Draft raw_app "a/admin_panel" has no policy to deploy.
// after: restore the draft's data/runnables so recomputeAppPolicy derives a policy
appDraft.data = { ...DEFAULT_RAW_APP_DATA, ...edits }
await deployDraft({ type: 'raw_app', path: 'a/admin_panel' }) Defensive patterns
Strategy: validation
Validate before calling
import { DEFAULT_RAW_APP_DATA } from '$lib/components/raw_apps/rawAppData'
const appDraft = (await getGlobalDraft(ws, 'raw_app', path))?.value
if (appDraft && (!appDraft.runnables || !appDraft.data)) {
appDraft.data = { ...DEFAULT_RAW_APP_DATA, ...(appDraft.data ?? {}) }
}
await deployDraft({ type: 'raw_app', path, workspace: ws }) Type guard
function rawAppDraftHasPolicyInputs(draft) {
return draft != null && draft.value != null &&
typeof draft.value === 'object' && 'runnables' in draft.value && 'data' in draft.value
} Try / catch
try {
await deployDraft({ type: 'raw_app', path, workspace })
} catch (e) {
if (/has no policy to deploy/.test(e.message)) {
// repair the draft's runnables/data in the editor, then retry
} else throw e
} Prevention
- Build raw app drafts on top of DEFAULT_RAW_APP_DATA instead of from scratch.
- Don't strip policy-relevant fields when programmatically editing drafts.
- Preview the app in the editor (which computes the policy) before deploying.
When it happens
Trigger: Deploying a raw_app whose draft, after policy recomputation, yields appValue.policy == null — e.g. malformed/absent policy-producing fields in the draft (runnables/data shape the policy computer cannot derive a policy from).
Common situations: A raw app draft created by the AI with a runnables/data shape missing what rawAppPolicy expects; hand-edited draft state that dropped the policy section; a DEFAULT_RAW_APP_DATA regression after schema changes.
Related errors
- Unknown kind: ${kind}
- result.substring(__RESULT_ERR_PREFIX.length)
- Invalid migration name '${name}': use only letters, digits,
- Unknown workspace dependencies file format: ${path}. Valid f
- Cannot push flow ${remotePath}: step(s) reference non-worksp
AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03).
Data as JSON: /api/errors/71b9a610058cf191.
Report an issue: GitHub.