getzola/zola · info

Could not build Method Not Allowed response

Error message

Could not build Method Not Allowed response

What it means

method_not_allowed builds a static 405 response with fully static headers and body, and .expect panics only if hyper's Response builder rejects them. With the current constants this is an unreachable invariant guard in the dev server.

Source

Thrown at src/cmd/serve.rs:369

            "json" => "application/json",
            "txt" => "text/plain",
            _ => "text/html",
        },
        None => "text/html",
    };
    Response::builder()
        .header(header::CONTENT_TYPE, content_type)
        .status(StatusCode::OK)
        .body(Body::from(content.to_owned()))
        .expect("Could not build HTML response")
}

fn method_not_allowed() -> Response {
    Response::builder()
        .header(header::CONTENT_TYPE, "text/plain")
        .status(StatusCode::METHOD_NOT_ALLOWED)
        .body(Body::from(METHOD_NOT_ALLOWED_TEXT))
        .expect("Could not build Method Not Allowed response")
}

fn io_error(err: std::io::Error) -> Response {
    match err.kind() {
        std::io::ErrorKind::NotFound => not_found(),
        std::io::ErrorKind::PermissionDenied => {
            Response::builder().status(StatusCode::FORBIDDEN).body(Body::empty()).unwrap()
        }
        _ => panic!("{}", err),
    }
}

fn not_found() -> Response {
    let not_found_path = RelativePath::new("404.html");
    let content = SITE_CONTENT.read().unwrap().get(not_found_path).cloned();

    if let Some(body) = content {
        return Response::builder()

View on GitHub (pinned to 61d3082821)

Solutions

  1. Keep headers/body static; verify constants compile as valid header values
  2. Build via Response::new(Body::from(...)) plus headers_mut() so construction is infallible
  3. Add a unit test exercising method_not_allowed to catch regressions

Example fix

// before
Response::builder()
    .header(header::CONTENT_TYPE, "text/plain")
    .status(StatusCode::METHOD_NOT_ALLOWED)
    .body(Body::from(METHOD_NOT_ALLOWED_TEXT))
    .expect("Could not build Method Not Allowed response")
// after
let mut response = Response::new(Body::from(METHOD_NOT_ALLOWED_TEXT));
*response.status_mut() = StatusCode::METHOD_NOT_ALLOWED;
response.headers_mut().insert(header::CONTENT_TYPE, HeaderValue::from_static("text/plain"));
response
Defensive patterns

Strategy: fallback

Validate before calling

let _ = http::HeaderValue::from_static("text/plain"); // compile-time-checked constant

Try / catch

match Response::builder()
    .header(header::CONTENT_TYPE, "text/plain")
    .status(StatusCode::METHOD_NOT_ALLOWED)
    .body(Body::from(METHOD_NOT_ALLOWED_TEXT))
{
    Ok(resp) => resp,
    Err(_) => StatusCode::METHOD_NOT_ALLOWED.into_response(),
}

Prevention

When it happens

Trigger: Issuing a non-GET request to the `zola serve` static server (triggering method_not_allowed) while the builder path fails — only possible if someone makes the headers/body dynamic and invalid.

Common situations: Refactoring the constant METHOD_NOT_ALLOWED_TEXT into dynamic content or altering header values with invalid characters, then testing a POST to the dev server.

Related errors


AI-assisted analysis of getzola/zola@61d3082821 (2026-09-03). Data as JSON: /api/errors/8244b98d7050760b. Report an issue: GitHub.