{"record":{"id":"fa2f8da17d8cacb8","repo":"windmill-labs/windmill","slug":"result-substring-result-err-prefix-length","errorCode":null,"errorMessage":"result.substring(__RESULT_ERR_PREFIX.length)","messagePattern":"result\\.substring\\(__RESULT_ERR_PREFIX\\.length\\)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"backend/windmill-jseval/src/lib.rs","lineNumber":774,"sourceCode":"                let client = state_for_user_state.client.clone();\n                let job_id = root_flow_job_id_for_state.clone();\n                async move {\n                    const ERR_PREFIX: &str = \"\\x00__WINDMILL_ERR__\\x00\";\n                    match client.get_flow_user_state(&job_id, &key).await {\n                        Ok(value) => {\n                            serde_json::to_string(&value).unwrap_or_else(|_| \"null\".to_string())\n                        }\n                        Err(e) => format!(\"{}{}\", ERR_PREFIX, e),\n                    }\n                }\n            }))),\n        )?;\n\n        let wrapper_code = r#\"\n            const __RESULT_ERR_PREFIX = '\\x00__WINDMILL_ERR__\\x00';\n            function __throwOrParse(result) {\n                if (typeof result === 'string' && result.startsWith(__RESULT_ERR_PREFIX)) {\n                    throw new Error(result.substring(__RESULT_ERR_PREFIX.length));\n                }\n                return JSON.parse(result);\n            }\n\n            async function __getResult(stepId) {\n                return __throwOrParse(await __fetchResult(stepId));\n            }\n\n            async function flow_user_state(key) {\n                return __throwOrParse(await __fetchFlowUserState(key));\n            }\n        \"#;\n        ctx.eval::<(), _>(wrapper_code)\n            .catch(ctx)\n            .map_err(quickjs_error_to_anyhow)?;\n    } else {\n        let stub_code = r#\"\n            function __getResult(stepId) {","sourceCodeStart":756,"sourceCodeEnd":792,"githubUrl":"https://github.com/windmill-labs/windmill/blob/e474e8803ce2ff5c2df09a58dab51d45f5c922ca/backend/windmill-jseval/src/lib.rs#L756-L792","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before (caller passes a number)\nawait wmill.runScript(..., { status: 2 })\n// after\nawait wmill.runScript(..., { status: 'active' })","handlingStrategy":"type-guard","validationCode":"function validateEnumArgs(args, signature) {\n  for (const p of signature.filter(p => p.type === 'enum')) {\n    const v = args[p.name];\n    if (typeof v !== 'string') throw new Error(`enum param '${p.name}' must be a string, got ${v === null ? 'null' : typeof v}`);\n    if (p.variants && !p.variants.includes(v)) throw new Error(`'${v}' not in [${p.variants}]`);\n  }\n}\nvalidateEnumArgs({ status: 'active' }, [{ name: 'status', type: 'enum', variants: ['active','inactive'] }]);","typeGuard":"const isEnumStr = (v, variants) => typeof v === 'string' && (!variants || variants.includes(v));","tryCatchPattern":"try {\n  await runSqlScript(path, { status: value });\n} catch (e) {\n  if (/needs to receive a string/.test(e.message)) {\n    const name = e.message.match(/`(.+)`/)?.[1];\n    throw new Error(`Pass '${name}' as a string matching the enum variants, got ${typeof value}`);\n  }\n  throw e;\n}","preventionTips":["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"],"tags":["sql","parameters","type-error","enum","validation"],"backgroundTag":"parameter-type-mismatch","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"}