{"record":{"id":"809fd09211f6586b","repo":"windmill-labs/windmill","slug":"supplied-schema-draft-version-is-unsuported","errorCode":null,"errorMessage":"Supplied schema draft version is unsuported","messagePattern":"Supplied schema draft version is unsuported","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/windmill-common/src/schema.rs","lineNumber":518,"sourceCode":"                let parsed_val = Value::from_str(raw_val.get()).map_err(|e| {\n                    Error::ArgumentErr(format!(\"Failed to parse `{key}` argument: {e}\"))\n                })?;\n                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","sourceCodeStart":500,"sourceCodeEnd":536,"githubUrl":"https://github.com/windmill-labs/windmill/blob/e474e8803ce2ff5c2df09a58dab51d45f5c922ca/backend/windmill-common/src/schema.rs#L500-L536","documentation":"Schema::from_schema only supports JSON Schema draft 2020-12 and requires the `$schema` keyword to say exactly \"https://json-schema.org/draft/2020-12/schema\". Any other declared draft (draft-07, 2019-09, http vs https, trailing differences) triggers this error. Note the message contains a typo (\"unsuported\").","triggerScenarios":"Passing a schema string to from_schema whose `$schema` is e.g. \"http://json-schema.org/draft-07/schema#\", \"https://json-schema.org/draft/2019-09/schema\", or a URL with different casing/format.","commonSituations":"Reusing schemas written for draft-07 (still the most common in the wild), schemas exported by editors defaulting to draft-04/07, and old http:// URLs instead of the https:// 2020-12 canonical URL.","solutions":["Set \"$schema\": \"https://json-schema.org/draft/2020-12/schema\" at the schema root.","If the schema uses draft-07 constructs, port them to 2020-12 (usually a direct match for basic type/required/properties/enum).","Check for exact-string issues: use https (not http) and no trailing '#' variants of a different URL."],"exampleFix":"// before\n{\"$schema\": \"http://json-schema.org/draft-07/schema#\", ...}\n// after\n{\"$schema\": \"https://json-schema.org/draft/2020-12/schema\", ...}","handlingStrategy":"validation","validationCode":"const SUPPORTED_DRAFT: &str = \"https://json-schema.org/draft/2020-12/schema\";\nfn validate_draft(schema: &serde_json::Value) -> Result<(), String> {\n    match schema.get(\"$schema\").and_then(|v| v.as_str()) {\n        Some(d) if d == SUPPORTED_DRAFT => Ok(()),\n        Some(d) => Err(format!(\"unsupported draft {d}; use {SUPPORTED_DRAFT}\")),\n        None => Err(\"missing $schema\".into()),\n    }\n}","typeGuard":"fn is_supported_draft(schema: &serde_json::Value) -> bool {\n    schema.get(\"$schema\").and_then(|v| v.as_str())\n        == Some(\"https://json-schema.org/draft/2020-12/schema\")\n}","tryCatchPattern":"match Schema::from_schema(&schema_str) {\n    Ok(s) => s,\n    Err(e) if e.to_string().contains(\"draft version\") => {\n        eprintln!(\"convert the schema to draft 2020-12 and set $schema accordingly: {e}\");\n        return Err(e);\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Pin every schema to \"$schema\": \"https://json-schema.org/draft/2020-12/schema\"","Migrate draft-07 schemas on ingestion; most basic keywords map 1:1","Compare the $schema URL exactly — http vs https and trailing fragments matter"],"tags":["json-schema","draft-version","schema-validation","windmill"],"backgroundTag":"unsupported-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"}