{"record":{"id":"3709032382ecc823","repo":"windmill-labs/windmill","slug":"cannot-parse-s-as-smallint-e","errorCode":null,"errorMessage":"Cannot parse '{s}' as smallint: {e}","messagePattern":"Cannot parse '(.+?)' as smallint: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/windmill-worker/src/pg_executor.rs","lineNumber":1583,"sourceCode":"                || arg_t == \"bigserial\"\n                || arg_t == \"int8\"\n                || arg_t == \"serial8\")\n                && n.is_u64() =>\n        {\n            Ok((Box::new(n.as_u64().unwrap() as i64), Type::INT8))\n        }\n        Value::Number(n) if n.is_i64() => Ok((Box::new(n.as_i64().unwrap()), Type::INT8)),\n        Value::Number(n) => Ok((Box::new(n.as_f64().unwrap()), Type::FLOAT8)),\n        Value::String(s) if arg_t == \"uuid\" => Ok((Box::new(Uuid::parse_str(s)?), Type::UUID)),\n        Value::String(s)\n            if arg_t == \"smallint\"\n                || arg_t == \"smallserial\"\n                || arg_t == \"int2\"\n                || arg_t == \"serial2\" =>\n        {\n            s.parse::<i16>()\n                .map(|n| (Box::new(n) as Box<dyn ToSql + Sync + Send>, Type::INT2))\n                .map_err(|e| anyhow::anyhow!(\"Cannot parse '{s}' as smallint: {e}\").into())\n        }\n        Value::String(s)\n            if arg_t == \"int\" || arg_t == \"integer\" || arg_t == \"int4\" || arg_t == \"serial\" =>\n        {\n            s.parse::<i32>()\n                .map(|n| (Box::new(n) as Box<dyn ToSql + Sync + Send>, Type::INT4))\n                .map_err(|e| anyhow::anyhow!(\"Cannot parse '{s}' as integer: {e}\").into())\n        }\n        Value::String(s)\n            if arg_t == \"bigint\"\n                || arg_t == \"bigserial\"\n                || arg_t == \"int8\"\n                || arg_t == \"serial8\" =>\n        {\n            s.parse::<i64>()\n                .map(|n| (Box::new(n) as Box<dyn ToSql + Sync + Send>, Type::INT8))\n                .map_err(|e| anyhow::anyhow!(\"Cannot parse '{s}' as bigint: {e}\").into())\n        }","sourceCodeStart":1565,"sourceCodeEnd":1601,"githubUrl":"https://github.com/windmill-labs/windmill/blob/e474e8803ce2ff5c2df09a58dab51d45f5c922ca/backend/windmill-worker/src/pg_executor.rs#L1565-L1601","documentation":"convert_val converts a JSON string argument into a tokio-postgres ToSql parameter. When the declared arg type is smallint (smallserial, int2, serial2), it parses the string with i16::from_str; on failure it wraps the ParseIntError into 'Cannot parse ... as smallint'. It exists because the executor takes string params from JSON and must produce a valid INT2 value client-side.","triggerScenarios":"A step argument typed smallint/int2 receives a Value::String whose content is not a valid i16 (out of range like '40000', empty string, non-numeric text, or with leading '+ ' or spaces).","commonSituations":"Form input passed straight through without validation; a value like '32768' exceeding i16 range; user typed '12,5' or '12.5' with a decimal; empty string from an unfilled field; locale-formatted numbers with thousand separators.","solutions":["Ensure the input string is a whole number within i16 range (-32768..=32767) before calling the step","Parse/trim the value in the step script (e.g. Number(str)) and re-submit as a number or validated string","If the value can exceed 32767, change the column/arg type to int/int4 or bigint/int8","Pass the value as a JS number instead of a string when the JSON schema allows it, so the numeric arm handles it"],"exampleFix":"// before\nargs: { count: \"40000\" }  // arg_t = smallint -> overflows i16\n// after\nargs: { count: \"40000\" }  // arg_t changed to int, or clamp: Math.min(32767, parseInt(count,10))","handlingStrategy":"validation","validationCode":"function assertSmallint(s) {\n  if (typeof s === \"string\") {\n    const n = Number(s);\n    if (!Number.isInteger(n) || n < -32768 || n > 32767) {\n      throw new Error(`value ${JSON.stringify(s)} is not a valid smallint (i16)`);\n    }\n  }\n}","typeGuard":"const isSmallint = (v) => Number.isInteger(Number(v)) && Number(v) >= -32768 && Number(v) <= 32767;","tryCatchPattern":"try {\n  await runPgStep(args);\n} catch (e) {\n  if (String(e.message).includes(\"as smallint\")) {\n    throw new Error(`Argument must be an integer in [-32768, 32767], got: ${e.message}`);\n  }\n  throw e;\n}","preventionTips":["Validate integer inputs and ranges at the form/UI layer","Reject decimals, thousands separators and empty strings before calling the step","Use int4/int8 when the range could exceed i16"],"tags":["postgresql","parse-error","integer","type-conversion"],"backgroundTag":"invalid-number-format","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"}