windmill-labs/windmill · error
Cannot parse '{s}' as oid: {e}
Error message
Cannot parse '{s}' as oid: {e} What it means
convert_val converts a JSON string argument into a tokio-postgres ToSql parameter. When the declared arg type is oid, it parses the string with u32::from_str and wraps any ParseIntError as 'Cannot parse ... as oid'. It exists to build a valid OID (unsigned 32-bit) parameter client-side.
Source
Thrown at backend/windmill-worker/src/pg_executor.rs:1659
Value::String(s) if arg_t == "numeric" || arg_t == "decimal" => s
.parse::<Decimal>()
.map(|d| (Box::new(d) as Box<dyn ToSql + Sync + Send>, Type::NUMERIC))
.map_err(|e| anyhow::anyhow!("Cannot parse '{s}' as numeric: {e}").into()),
Value::String(s) if arg_t == "real" || arg_t == "float4" => s
.parse::<f32>()
.map(|n| (Box::new(n) as Box<dyn ToSql + Sync + Send>, Type::FLOAT4))
.map_err(|e| anyhow::anyhow!("Cannot parse '{s}' as real: {e}").into()),
Value::String(s)
if arg_t == "double" || arg_t == "double precision" || arg_t == "float8" =>
{
s.parse::<f64>()
.map(|n| (Box::new(n) as Box<dyn ToSql + Sync + Send>, Type::FLOAT8))
.map_err(|e| anyhow::anyhow!("Cannot parse '{s}' as double: {e}").into())
}
Value::String(s) if arg_t == "oid" => s
.parse::<u32>()
.map(|n| (Box::new(n) as Box<dyn ToSql + Sync + Send>, Type::OID))
.map_err(|e| anyhow::anyhow!("Cannot parse '{s}' as oid: {e}").into()),
Value::String(s) if arg_t == "bool" || arg_t == "boolean" => {
// Accept the same literals Postgres' boolin() does.
let b = match s.to_ascii_lowercase().as_str() {
"true" | "t" | "yes" | "y" | "1" | "on" => true,
"false" | "f" | "no" | "n" | "0" | "off" => false,
_ => {
return Err(
anyhow::anyhow!("Cannot parse '{s}' as bool: invalid literal").into(),
)
}
};
Ok((Box::new(b), Type::BOOL))
}
Value::String(s) if arg_t == "varchar" || arg_t == "character varying" => {
Ok((Box::new(s.clone()), Type::VARCHAR))
}
// For arg_t in (json, jsonb): bind a JSON-encodable Value with the
// matching pg type. Falling through to TEXT here would assert TEXTView on GitHub (pinned to e474e8803c)
Solutions
- Ensure the value is a non-negative integer that fits in u32 (0..=4294967295)
- Resolve object names to numeric OIDs in the query itself (e.g. `SELECT 'my_table'::regclass::oid`) instead of passing names as oid args
- If the value can be negative or larger, the type is wrong — use int8 or numeric
- Trim the string before passing to remove stray whitespace
Example fix
// before
args: { table_oid: "users" } // object name, not a numeric OID
// after
-- query uses: WHERE oid = 'users'::regclass::oid
args: { table_oid: "16584" } Defensive patterns
Strategy: validation
Validate before calling
function assertOid(s) {
const raw = typeof s === "string" ? s.trim() : s;
const n = Number(raw);
if (!Number.isInteger(n) || n < 0 || n > 4294967295) {
throw new Error(`value ${JSON.stringify(s)} is not a valid OID (u32)`);
}
} Type guard
const isOid = (v) => Number.isInteger(Number(v)) && Number(v) >= 0 && Number(v) <= 4294967295;
Try / catch
try {
await runPgStep(args);
} catch (e) {
if (String(e.message).includes("as oid")) {
throw new Error(`Argument must be a numeric OID in [0, 4294967295], got: ${e.message}`);
}
throw e;
} Prevention
- Resolve object names to OIDs with ::regclass::oid inside the query, not in application code
- Never pass object names or negative numbers to oid-typed args
- Trim numeric strings before passing
When it happens
Trigger: A step argument typed oid receives a Value::String that is not a valid u32: negative numbers, values above 4294967295, non-numeric text, or whitespace-padded strings.
Common situations: Passing a PG object name (e.g. 'regclass' style names) where a numeric OID is expected; signed integers copied from a query result; using a full function signature string instead of its OID number.
Related errors
- Cannot parse '{s}' as smallint: {e}
- Cannot parse '{s}' as integer: {e}
- Cannot parse '{s}' as bigint: {e}
- Cannot parse '{s}' as numeric: {e}
- Cannot parse '{s}' as real: {e}
AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03).
Data as JSON: /api/errors/7ba1c2e239a76fc8.
Report an issue: GitHub.