{"record":{"id":"04b0c1862bcc8efd","repo":"windmill-labs/windmill","slug":"mixed-types-in-array","errorCode":null,"errorMessage":"Mixed types in array","messagePattern":"Mixed types in array","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/windmill-worker/src/pg_executor.rs","lineNumber":1235,"sourceCode":"fn map_as_single_type<T>(\n    vec: Option<&Vec<Value>>,\n    f: impl Fn(&Value) -> Option<T>,\n) -> anyhow::Result<Option<Vec<Option<T>>>> {\n    if let Some(vec) = vec {\n        Ok(Some(\n            vec.into_iter()\n                .map(|v| {\n                    // first option is if the value is of the right type (if none, will stop the collection and throw error)\n                    // second option is if the value is null\n                    // allow nulls in arrays\n                    if matches!(v, Value::Null) {\n                        Some(None)\n                    } else {\n                        f(v).map(Some)\n                    }\n                })\n                .collect::<Option<Vec<Option<T>>>>()\n                .ok_or_else(|| anyhow::anyhow!(\"Mixed types in array\"))?,\n        ))\n    } else {\n        Ok(None)\n    }\n}\n\n/// A boxed `ToSql` value paired with the Postgres `Type` that matches its\n/// concrete Rust type. Returned by `convert_val` / `convert_vec_val` so the\n/// dispatch in `do_postgresql_inner` always asserts the type that the encoder\n/// can actually produce — never a parser-derived guess that drifts from the\n/// runtime binding.\ntype ConvertedParam = (Box<dyn ToSql + Sync + Send>, Type);\n\nfn convert_vec_val(\n    vec: Option<&Vec<Value>>,\n    arg_t: &String,\n) -> windmill_common::error::Result<ConvertedParam> {\n    match arg_t.as_str() {","sourceCodeStart":1217,"sourceCodeEnd":1253,"githubUrl":"https://github.com/windmill-labs/windmill/blob/e474e8803ce2ff5c2df09a58dab51d45f5c922ca/backend/windmill-worker/src/pg_executor.rs#L1217-L1253","documentation":"When converting a JSON array argument to a single-typed PostgreSQL array, `map_as_single_type` maps every element through the same converter `f`. If any conversion returns `None`, the elements are of mixed/incompatible types for the target array type, and the collect yields None -> this error. PostgreSQL arrays are homogeneous, so mixed element types cannot be bound as one parameter.","triggerScenarios":"`convert_vec_val` handling an array arg whose elements don't all fit the resolved element type — e.g. `[1, \"two\", null-ish object]` against `int[]`, or a heterogeneous JSON array bound to any declared array type.","commonSituations":"Users passing `[1, '2', 'three']` from JS/Python where strings and numbers mix; JSON input from webhooks with inconsistent element shapes; nested arrays where a flat array type was declared; objects accidentally included in an otherwise numeric array.","solutions":["Normalize the array in your script before passing it: ensure every element is the same type (e.g. map all to numbers or strings).","If nulls are intentional, confirm the declared element type allows NULL and elements are otherwise homogeneous.","Declare the correct arg otyp (e.g. `text[]` vs `int[]`) matching your actual data.","Flatten nested arrays into one level, or pass JSONB instead of an array type and cast in SQL."],"exampleFix":"// before: mixed types\nconst ids = [1, \"2\", \"3\"];  // int[] fails\n// after\nconst ids = [1, 2, 3]; // or [\"1\",\"2\",\"3\"] for text[]","handlingStrategy":"validation","validationCode":"// validate homogeneity before passing an array arg\nfunction isHomogeneous(arr) {\n  const kinds = new Set(arr.map(v => v === null ? 'null' : typeof v));\n  return kinds.size <= 2 && !(kinds.has('object'));\n}\n// throw if !isHomogeneous(myArray)","typeGuard":"fn all_same_type(v: &[serde_json::Value], f: impl Fn(&serde_json::Value) -> Option<T>) -> bool {\n    v.iter().all(|x| f(x).is_some())\n}","tryCatchPattern":null,"preventionTips":["Coerce array elements to one type before passing (e.g. .map(Number))","Match the declared array otyp (int[] vs text[]) to your data","Use JSONB with an in-SQL cast for genuinely heterogeneous payloads","Flatten nested arrays before binding"],"tags":["postgresql","array","type-mismatch","parameters"],"backgroundTag":"mixed-types-in-array","analyzedSha":"e474e8803ce2ff5c2df09a58dab51d45f5c922ca","analyzedAt":"2026-09-03T12:38:19.024Z","contentChangedAt":"2026-09-03T12:38:19.024Z","schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}