{"record":{"id":"7ba1c2e239a76fc8","repo":"windmill-labs/windmill","slug":"cannot-parse-s-as-oid-e","errorCode":null,"errorMessage":"Cannot parse '{s}' as oid: {e}","messagePattern":"Cannot parse '(.+?)' as oid: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/windmill-worker/src/pg_executor.rs","lineNumber":1659,"sourceCode":"        Value::String(s) if arg_t == \"numeric\" || arg_t == \"decimal\" => s\n            .parse::<Decimal>()\n            .map(|d| (Box::new(d) as Box<dyn ToSql + Sync + Send>, Type::NUMERIC))\n            .map_err(|e| anyhow::anyhow!(\"Cannot parse '{s}' as numeric: {e}\").into()),\n        Value::String(s) if arg_t == \"real\" || arg_t == \"float4\" => s\n            .parse::<f32>()\n            .map(|n| (Box::new(n) as Box<dyn ToSql + Sync + Send>, Type::FLOAT4))\n            .map_err(|e| anyhow::anyhow!(\"Cannot parse '{s}' as real: {e}\").into()),\n        Value::String(s)\n            if arg_t == \"double\" || arg_t == \"double precision\" || arg_t == \"float8\" =>\n        {\n            s.parse::<f64>()\n                .map(|n| (Box::new(n) as Box<dyn ToSql + Sync + Send>, Type::FLOAT8))\n                .map_err(|e| anyhow::anyhow!(\"Cannot parse '{s}' as double: {e}\").into())\n        }\n        Value::String(s) if arg_t == \"oid\" => s\n            .parse::<u32>()\n            .map(|n| (Box::new(n) as Box<dyn ToSql + Sync + Send>, Type::OID))\n            .map_err(|e| anyhow::anyhow!(\"Cannot parse '{s}' as oid: {e}\").into()),\n        Value::String(s) if arg_t == \"bool\" || arg_t == \"boolean\" => {\n            // Accept the same literals Postgres' boolin() does.\n            let b = match s.to_ascii_lowercase().as_str() {\n                \"true\" | \"t\" | \"yes\" | \"y\" | \"1\" | \"on\" => true,\n                \"false\" | \"f\" | \"no\" | \"n\" | \"0\" | \"off\" => false,\n                _ => {\n                    return Err(\n                        anyhow::anyhow!(\"Cannot parse '{s}' as bool: invalid literal\").into(),\n                    )\n                }\n            };\n            Ok((Box::new(b), Type::BOOL))\n        }\n        Value::String(s) if arg_t == \"varchar\" || arg_t == \"character varying\" => {\n            Ok((Box::new(s.clone()), Type::VARCHAR))\n        }\n        // For arg_t in (json, jsonb): bind a JSON-encodable Value with the\n        // matching pg type. Falling through to TEXT here would assert TEXT","sourceCodeStart":1641,"sourceCodeEnd":1677,"githubUrl":"https://github.com/windmill-labs/windmill/blob/e474e8803ce2ff5c2df09a58dab51d45f5c922ca/backend/windmill-worker/src/pg_executor.rs#L1641-L1677","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nargs: { table_oid: \"users\" }  // object name, not a numeric OID\n// after\n-- query uses: WHERE oid = 'users'::regclass::oid\nargs: { table_oid: \"16584\" }","handlingStrategy":"validation","validationCode":"function assertOid(s) {\n  const raw = typeof s === \"string\" ? s.trim() : s;\n  const n = Number(raw);\n  if (!Number.isInteger(n) || n < 0 || n > 4294967295) {\n    throw new Error(`value ${JSON.stringify(s)} is not a valid OID (u32)`);\n  }\n}","typeGuard":"const isOid = (v) => Number.isInteger(Number(v)) && Number(v) >= 0 && Number(v) <= 4294967295;","tryCatchPattern":"try {\n  await runPgStep(args);\n} catch (e) {\n  if (String(e.message).includes(\"as oid\")) {\n    throw new Error(`Argument must be a numeric OID in [0, 4294967295], got: ${e.message}`);\n  }\n  throw e;\n}","preventionTips":["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"],"tags":["postgresql","parse-error","oid","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"}