windmill-labs/windmill · error

Empty parameter name in path: {}

Error message

Empty parameter name in path: {}

What it means

from_route_path_to_openapi_path converts Windmill's route syntax (':param' segments) into OpenAPI '{param}' syntax. When a route path contains a segment starting with ':' but with no name after it (e.g. '/api/foo/:/bar'), the conversion fails with 'Empty parameter name in path: {}'. This is a guard against generating invalid OpenAPI path templates.

Source

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

            security_scheme,
            args_schema,
        }
    }
}

fn from_route_path_to_openapi_path(
    route_path: &str,
    kind: &Kind,
) -> Result<(Vec<String>, Option<Value>)> {
    let mut openapi_path = String::new();
    let mut parameters = Vec::new();

    for segment in route_path.split('/') {
        if segment.starts_with(':') {
            let param_name = &segment[1..];

            if param_name.is_empty() {
                return Err(anyhow!("Empty parameter name in path: {}", route_path).into());
            }

            openapi_path.push_str(&format!("/{{{}}}", param_name));
            parameters.push(serde_json::json!({
                "name": param_name,
                "in": "path",
                "required": true,
                "schema": { "type": "string" }
            }));
        } else if !segment.is_empty() {
            openapi_path.push('/');
            openapi_path.push_str(segment);
        } else {
            openapi_path.push('/');
        }
    }

    let parameters_json = if parameters.is_empty() {

View on GitHub (pinned to e474e8803c)

Solutions

  1. Fix the route definition to give the parameter a name (e.g. /:workspace_id instead of /:)
  2. Check code that builds route paths dynamically for empty string variables
  3. Add a registration-time assertion rejecting routes with empty parameter names

Example fix

// before
let route = format!("/api/w/{}/run/:", workspace); // dangling colon
// after
let route = format!("/api/w/{}/run/:job_id", workspace);
Defensive patterns

Strategy: validation

Validate before calling

fn validate_route_path(p: &str) -> Result<(), String> {
    for seg in p.split('/') {
        if seg.starts_with(':') && seg.len() <= 1 {
            return Err(format!("empty parameter name in path {p}"));
        }
    }
    Ok(())
}

Try / catch

match from_route_path_to_openapi_path(path) {
    Ok(openapi_path) => openapi_path,
    Err(e) => {
        tracing::error!("route path invalid: {e:#}");
        skip_path_and_continue(path)
    }
}

Prevention

When it happens

Trigger: A route registered with a path containing a bare ':' segment or a trailing ':' (e.g. 'prefix/:') passed into generate_paths -> from_route_path_to_openapi_path.

Common situations: Programmatic path construction bugs where a variable holding the param name is empty; typos in route definitions; concatenating path fragments that leave a dangling colon.

Related errors


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