{"record":{"id":"522b38695655ba52","repo":"windmill-labs/windmill","slug":"no-draft-version-supplied","errorCode":null,"errorMessage":"No draft version supplied","messagePattern":"No draft version supplied","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/windmill-common/src/schema.rs","lineNumber":521,"sourceCode":"                for rule in rules {\n                    rule.apply_rule(key, &parsed_val, self.required.contains(key))?;\n                }\n            }\n        }\n\n        Ok(())\n    }\n\n    pub fn from_schema(schema: &str) -> Result<Self, Error> {\n        let schema: Value = serde_json::from_str(schema)?;\n\n        if let Some(draft_version) = schema.get(\"$schema\") {\n            match draft_version.as_str() {\n                Some(\"https://json-schema.org/draft/2020-12/schema\") => (),\n                _ => return Err(anyhow!(\"Supplied schema draft version is unsuported\").into()),\n            }\n        } else {\n            return Err(anyhow!(\"No draft version supplied\").into());\n        }\n\n        let required: Vec<String> = schema\n            .get(\"required\")\n            .ok_or(anyhow!(\"Missing `required` field on schema\"))?\n            .as_array()\n            .ok_or(anyhow!(\"`required` field should be an array of strings\"))?\n            .into_iter()\n            .map(|v| {\n                v.as_str()\n                    .map(|s| s.to_string())\n                    .ok_or(anyhow!(\"required field key is not a string\"))\n            })\n            .collect::<Result<Vec<String>, anyhow::Error>>()?;\n\n        let properties = schema\n            .get(\"properties\")\n            .ok_or(anyhow!(\"Missing `properties` field on schema\"))?","sourceCodeStart":503,"sourceCodeEnd":539,"githubUrl":"https://github.com/windmill-labs/windmill/blob/e474e8803ce2ff5c2df09a58dab51d45f5c922ca/backend/windmill-common/src/schema.rs#L503-L539","documentation":"from_schema requires the `$schema` keyword declaring the draft version; a schema without it is rejected rather than assumed. Windmill deliberately refuses to guess the draft so validation semantics are unambiguous.","triggerScenarios":"Calling Schema::from_schema with a JSON schema string that has no top-level `$schema` key — common for minimal schemas like {\"type\":\"object\",\"properties\":{...},\"required\":[...]}.","commonSituations":"Hand-written minimal schemas, schemas copied from tools that omit `$schema`, and dynamically built schemas serialized from objects without adding the keyword.","solutions":["Add \"$schema\": \"https://json-schema.org/draft/2020-12/schema\" as a top-level key of the schema.","If the schema is generated in code, ensure the generator always injects the `$schema` field before serialization."],"exampleFix":"// before\n{\"type\": \"object\", \"properties\": {...}, \"required\": [...]}\n// after\n{\"$schema\": \"https://json-schema.org/draft/2020-12/schema\", \"type\": \"object\", \"properties\": {...}, \"required\": [...]}\n","handlingStrategy":"validation","validationCode":"fn require_draft_field(schema: &serde_json::Value) -> Result<(), String> {\n    if schema.get(\"$schema\").is_none() {\n        Err(\"add top-level $schema: https://json-schema.org/draft/2020-12/schema\".into())\n    } else { Ok(()) }\n}","typeGuard":"fn has_draft(schema: &serde_json::Value) -> bool {\n    schema.get(\"$schema\").is_some()\n}","tryCatchPattern":"match Schema::from_schema(&schema_str) {\n    Ok(s) => s,\n    Err(e) if e.to_string().contains(\"No draft version supplied\") => {\n        eprintln!(\"inject $schema into the schema before calling from_schema\");\n        return Err(e);\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Make $schema a mandatory field in any schema template or generator","When building schemas programmatically, always insert $schema at the root before serialization"],"tags":["json-schema","schema-validation","missing-field","windmill"],"backgroundTag":"missing-schema-draft","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"}