{"record":{"id":"54a28a4218e9b820","repo":"windmill-labs/windmill","slug":"cannot-turn-secret-variable-args-path-into-a","errorCode":null,"errorMessage":"Cannot turn secret variable \"${args.path}\" into a non-secret one without a value: its stored value cannot be read, so it would be replaced by an empty one. Pass the new plaintext value, or leave is_secret unset to keep it secret.","messagePattern":"Cannot turn secret variable \"(.+?)\" into a non-secret one without a value: its stored value cannot be read, so it would be replaced by an empty one\\. Pass the new plaintext value, or leave is_secret unset to keep it secret\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"frontend/src/lib/components/copilot/chat/global/core.ts","lineNumber":4696,"sourceCode":"\t\t)\n\t}\n\t// Securing one needs a value too when it holds none: the deploy would send no `value`\n\t// (nothing is staged) and the backend refuses an is_secret change without one. Saying\n\t// so here keeps the model from having to interpret that error.\n\tif (\n\t\tis_secret &&\n\t\tbase?.variable.is_secret === false &&\n\t\t(args.value ?? base.variable.value) === ''\n\t) {\n\t\tthrow new Error(\n\t\t\t`Cannot make variable \"${args.path}\" secret without a value: it currently holds an empty one, so there would be nothing to encrypt. Pass the value it should hold.`\n\t\t)\n\t}\n\t// Un-securing always needs a new plaintext value. An `$encrypted:` marker is no\n\t// help: the deploy endpoints only decrypt it while the target stays secret, so\n\t// carrying it into a non-secret variable would store the marker as the value.\n\tif (is_secret === false && base?.variable.is_secret === true && args.value === undefined) {\n\t\tthrow new Error(\n\t\t\t`Cannot turn secret variable \"${args.path}\" into a non-secret one without a value: its stored value cannot be read, so it would be replaced by an empty one. Pass the new plaintext value, or leave is_secret unset to keep it secret.`\n\t\t)\n\t}\n\treturn {\n\t\tis_secret,\n\t\tvalue: args.value ?? base?.variable.value ?? '',\n\t\tdescription: args.description ?? base?.variable.description ?? ''\n\t}\n}\n\nfunction createVariableToDraftState(\n\targs: WriteVariableArgs,\n\tbase?: VariableDraftState\n): VariableDraftState {\n\tconst { is_secret, value, description } = resolveVariableWrite(args, base)\n\treturn {\n\t\t...base,\n\t\tpath: args.path,","sourceCodeStart":4678,"sourceCodeEnd":4714,"githubUrl":"https://github.com/windmill-labs/windmill/blob/e474e8803ce2ff5c2df09a58dab51d45f5c922ca/frontend/src/lib/components/copilot/chat/global/core.ts#L4678-L4714","documentation":"Un-securing a secret variable requires a new plaintext value because the stored value is unreadable ($encrypted marker) outside a secret target. Without a value the variable would be replaced by an empty one, so the tool refuses and asks for plaintext or to leave is_secret unset.","triggerScenarios":"A write_variable call where args.is_secret === false and the base variable is_secret is true and args.value is undefined.","commonSituations":"The model tries to make a secret readable for debugging without realizing the plaintext is unrecoverable from the draft.","solutions":["Pass the new plaintext value together with is_secret: false","Leave is_secret unset (keep the variable secret) if you don't have the plaintext","Store the secret's value elsewhere first if you need it in non-secret form"],"exampleFix":"// before\nwriteVariable({ path: 'u/admin/API_KEY', is_secret: false })\n// after\nwriteVariable({ path: 'u/admin/API_KEY', is_secret: false, value: 'plain-value' })","handlingStrategy":"validation","validationCode":"if (args.is_secret === false && baseIsSecret && args.value === undefined) {\n  throw new Error('unsecuring needs a plaintext value');\n}","typeGuard":"function canUnsecret(args) { return args.is_secret !== false || typeof args.value === 'string'; }","tryCatchPattern":"try { writeVariable(args) } catch (e) { if (e.message.includes('into a non-secret')) supplyPlaintextOrAbort(); }","preventionTips":["Remember secret plaintext is unrecoverable once stored encrypted","Provide plaintext when unsecuring, or leave is_secret unset"],"tags":["ai-copilot","secrets","variables","encrypted-value"],"backgroundTag":"secret-to-plaintext-conversion","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"}