windmill-labs/windmill · error
Unsupported value for type field, expected string or string
Error message
Unsupported value for type field, expected string or string array
What it means
Windmill parses JSON Schema property definitions into validation rules via SchemaValidationRule::from_value. The `type` field must be either a string (e.g. "object") or an array of such strings (a type union); anything else (number, object, null) is rejected. This is a schema-authoring error detected when the schema is loaded, not when data is validated.
Source
Thrown at backend/windmill-common/src/schema.rs:181
val,
)?);
} else if let Some(typ_arr) = typ.as_array() {
let typ_arr = typ_arr
.into_iter()
.map(|v| {
SchemaValidationRule::from_primitive(
&JsonPrimitiveType::from_str(
v.as_str()
.ok_or(anyhow!("Expected array of strings for `type` field"))?,
)?,
v,
)
})
.collect::<Result<Vec<Vec<SchemaValidationRule>>, anyhow::Error>>()?;
schema_rules.push(SchemaValidationRule::IsUnionType(typ_arr));
} else {
return Err(anyhow!(
"Unsupported value for type field, expected string or string array"
)
.into());
}
if let Some(enum_variants) = val.get("enum") {
let variants = enum_variants
.as_array()
.ok_or(anyhow!("enum variants are not in an array"))?
.clone();
schema_rules.push(SchemaValidationRule::StrictEnum(variants));
}
Ok(schema_rules)
}
fn apply_rule(&self, key: &str, val: &Value, required: bool) -> Result<(), Error> {
if val.is_null() {View on GitHub (pinned to e474e8803c)
Solutions
- Set `type` to a supported string: object, array, string, number, integer, boolean, or null.
- If multiple types are intended, use an array of strings, e.g. "type": ["string","null"].
- If the property is a union of shapes, use `anyOf` with sub-schemas instead of a complex `type`.
- Remove the property or fix the generator/template that produced the malformed `type` value.
Example fix
// before
{"myProp": {"type": 1}}
// after
{"myProp": {"type": "integer"}} Defensive patterns
Strategy: validation
Validate before calling
fn validate_type_field(prop: &serde_json::Value) -> Result<(), String> {
let t = prop.get("type").ok_or("missing type")?;
let ok = t.as_str().is_some()
|| t.as_array().map(|a| a.iter().all(|v| v.is_string())).unwrap_or(false);
if ok { Ok(()) } else { Err("type must be a string or array of strings".into()) }
} Type guard
fn has_valid_type(prop: &serde_json::Value) -> bool {
match prop.get("type") {
Some(v) if v.is_string() => true,
Some(v) if v.is_array() => v.as_array().unwrap().iter().all(|x| x.is_string()),
_ => false,
}
} Try / catch
match Schema::from_schema(&schema_str) {
Ok(s) => s,
Err(e) if e.to_string().contains("Unsupported value for type field") => {
eprintln!("schema has a malformed `type` value: {e}");
return Err(e);
}
Err(e) => return Err(e),
} Prevention
- Only use the seven primitive type strings: object, array, string, number, integer, boolean, null
- Express nullable fields as "type": ["string","null"] arrays, not null values
- Use anyOf for unions of object shapes instead of exotic type values
- Run the schema through a 2020-12 JSON Schema validator before deploying
When it happens
Trigger: Calling SchemaValidationRule::from_value (indirectly through Schema::from_schema, e.g. when an app inline script's schema is reduced by reduce_app) with a property whose `type` is a non-string, non-array JSON value such as {"type": 1}, {"type": {"a":"b"}}, or {"type": true}.
Common situations: Hand-written or generated schemas where `type` was mistyped, a tool emitted `type: null` for optional fields, a schema generator produced a boolean-schema-like form, or someone confused `type` with `$ref`/`anyOf` composition.
Related errors
- Field properties should be an object
- enum variants are not in an array
- Supplied schema draft version is unsuported
- No draft version supplied
- Missing `required` field on schema
AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03).
Data as JSON: /api/errors/98dea70e9eacf2d2.
Report an issue: GitHub.