windmill-labs/windmill · error · Error
result.substring(__RESULT_ERR_PREFIX.length)
Error message
result.substring(__RESULT_ERR_PREFIX.length)
What it means
For parameters typed as sanitized enums (string with allowed variants, SANITIZED_ENUM_STR), Windmill interpolates the argument into the SQL query only if the supplied runtime value is a string. If the argument is missing or not a JSON string, this error names the parameter.
Source
Thrown at backend/windmill-jseval/src/lib.rs:774
let client = state_for_user_state.client.clone();
let job_id = root_flow_job_id_for_state.clone();
async move {
const ERR_PREFIX: &str = "\x00__WINDMILL_ERR__\x00";
match client.get_flow_user_state(&job_id, &key).await {
Ok(value) => {
serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string())
}
Err(e) => format!("{}{}", ERR_PREFIX, e),
}
}
}))),
)?;
let wrapper_code = r#"
const __RESULT_ERR_PREFIX = '\x00__WINDMILL_ERR__\x00';
function __throwOrParse(result) {
if (typeof result === 'string' && result.startsWith(__RESULT_ERR_PREFIX)) {
throw new Error(result.substring(__RESULT_ERR_PREFIX.length));
}
return JSON.parse(result);
}
async function __getResult(stepId) {
return __throwOrParse(await __fetchResult(stepId));
}
async function flow_user_state(key) {
return __throwOrParse(await __fetchFlowUserState(key));
}
"#;
ctx.eval::<(), _>(wrapper_code)
.catch(ctx)
.map_err(quickjs_error_to_anyhow)?;
} else {
let stub_code = r#"
function __getResult(stepId) {View on GitHub (pinned to e474e8803c)
Solutions
- Pass the parameter as a plain JSON string whose value is one of the enum's allowed variants
- Convert numbers/other types to strings at the caller (e.g. String(value) or .toString()) before invoking the script
- Provide a default string value for the parameter in the script signature
- Check flow step input mappings and app form components so they emit strings, not raw typed values
Example fix
// before (caller passes a number)
await wmill.runScript(..., { status: 2 })
// after
await wmill.runScript(..., { status: 'active' }) Defensive patterns
Strategy: type-guard
Validate before calling
function validateEnumArgs(args, signature) {
for (const p of signature.filter(p => p.type === 'enum')) {
const v = args[p.name];
if (typeof v !== 'string') throw new Error(`enum param '${p.name}' must be a string, got ${v === null ? 'null' : typeof v}`);
if (p.variants && !p.variants.includes(v)) throw new Error(`'${v}' not in [${p.variants}]`);
}
}
validateEnumArgs({ status: 'active' }, [{ name: 'status', type: 'enum', variants: ['active','inactive'] }]); Type guard
const isEnumStr = (v, variants) => typeof v === 'string' && (!variants || variants.includes(v));
Try / catch
try {
await runSqlScript(path, { status: value });
} catch (e) {
if (/needs to receive a string/.test(e.message)) {
const name = e.message.match(/`(.+)`/)?.[1];
throw new Error(`Pass '${name}' as a string matching the enum variants, got ${typeof value}`);
}
throw e;
} Prevention
- Always bind enum params as strings, never numbers/null/objects
- Declare defaults for enum parameters in script signatures
- Check flow/app input mappings emit strings for enum fields
- Validate values against the declared variants client-side
When it happens
Trigger: Calling a postgresql/mysql/mssql/duckdb/bigquery/oracledb script whose signature has an enum (Str with variants) parameter, while passing a non-string JSON value (number, null, object, bool) or omitting the argument entirely.
Common situations: Passing an integer or null for an enum-typed path/query param from a flow step; frontend/app form sending raw JSON where the caller assumed coercion; API calls with missing payload keys; workflow variables bound to the wrong type.
Related errors
- ${scriptPath} declares no S3Object parameter to bind --uploa
- Flow modules must be an array
- Flow groups must be an array
- Invalid group at index ${index}: must be an object
- Code parameter is required and must be a string
AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03).
Data as JSON: /api/errors/fa2f8da17d8cacb8.
Report an issue: GitHub.