windmill-labs/windmill · error

Could not generate OpenAPI document in YAML format: {}

Error message

Could not generate OpenAPI document in YAML format: {}

What it means

generate_openapi_document serializes the assembled OpenAPI document; in YAML format it uses serde_yml::to_string and wraps any serialization failure as 'Could not generate OpenAPI document in YAML format: {}'. Thrown when the in-memory document Value cannot be converted to a YAML string.

Source

Thrown at backend/windmill-api-openapi/src/lib.rs:638

    url: Option<&Url>,
    paths: Vec<FuturePath>,
    format: Format,
) -> Result<String> {
    let mut openapi_doc: IndexMap<&'static str, Value> = IndexMap::new();

    openapi_doc.insert("openapi", to_value(&DEFAULT_OPENAPI_GENERATED_VERSION)?);
    openapi_doc.insert(
        "info",
        to_value(info.unwrap_or(&DEFAULT_OPENAPI_INFO_OBJECT))?,
    );

    openapi_doc.insert("components", Value::Object(generate_components(&paths)));

    openapi_doc.insert("paths", to_value(generate_paths(paths, url)?)?);

    let openapi_document = match format {
        Format::YAML => serde_yml::to_string(&openapi_doc).map_err(|err| {
            anyhow!(
                "Could not generate OpenAPI document in YAML format: {}",
                err
            )
        })?,
        Format::JSON => serde_json::to_string_pretty(&openapi_doc).map_err(|err| {
            anyhow!(
                "Could not generate OpenAPI document in JSON format: {}",
                err
            )
        })?,
    };

    Ok(openapi_document)
}

#[allow(unused)]
#[derive(Debug, Deserialize)]
struct HttpRouteFilter {

View on GitHub (pinned to e474e8803c)

Solutions

  1. Inspect the wrapped error message to find the non-serializable value and fix the generator that inserts it
  2. Test with format=JSON (serde_json) to confirm the document itself is valid and the issue is YAML-specific
  3. Check/align serde_yml crate versions in Cargo.lock
  4. Validate any custom x- extension objects use string keys

Example fix

// before
openapi_doc.insert("x-custom", serde_json::json!({123: "key"})); // non-string key
// after
openapi_doc.insert("x-custom", serde_json::json!({"123": "key"}));
Defensive patterns

Strategy: try-catch

Validate before calling

// ensure values are serializable before insertion
let v = serde_yml::to_value(&component)?; // fails early, clear error

Try / catch

match generate_openapi_document(paths, url, Format::YAML) {
    Ok(doc) => doc,
    Err(e) if e.to_string().contains("YAML format") => {
        tracing::error!("yaml spec generation failed: {e:#}");
        generate_openapi_document(paths, url, Format::JSON)? // fallback
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling generate_openapi_document (via generate_openapi_spec or download_spec endpoint) with format=YAML when the document contains values serde_yml cannot serialize (e.g. non-string map keys, invalid Value variants injected by generators).

Common situations: A newly added component or path generator inserts a JSON value that is not YAML-representable; serde_yml version incompatibility; corrupted extension fields (x-*) added to the document.

Related errors


AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03). Data as JSON: /api/errors/fd7afdf0ec40265d. Report an issue: GitHub.