{"record":{"id":"804e9460b738ddc7","repo":"getzola/zola","slug":"could-not-build-livereload-js-response","errorCode":null,"errorMessage":"Could not build livereload.js response","messagePattern":"Could not build livereload\\.js response","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"info","filePath":"src/cmd/serve.rs","lineNumber":271,"sourceCode":"                    Some(Err(e)) => {\n                        log::error!(\"WebSocket error: {e}\");\n                        break;\n                    }\n                    None => break,\n                }\n            }\n        }\n    }\n}\n\n/// Serve livereload.js\nasync fn serve_livereload_js() -> impl IntoResponse {\n    Response::builder()\n        .header(header::CONTENT_TYPE, \"text/javascript\")\n        .header(header::ACCESS_CONTROL_ALLOW_ORIGIN, \"*\")\n        .status(StatusCode::OK)\n        .body(Body::from(LIVE_RELOAD))\n        .expect(\"Could not build livereload.js response\")\n}\n\n/// Inserts build error message boxes into HTML responses when needed.\n/// Used as axum middleware via `map_response`.\nasync fn error_injection_middleware(response: Response) -> Response {\n    use axum::body::to_bytes;\n\n    // Return response as-is if there are no error messages.\n    let has_error = SERVE_ERROR.lock().unwrap().get_mut().is_some();\n    if !has_error {\n        return response;\n    }\n\n    // Only inject errors into HTML responses or 404 responses.\n    // Don't interfere with WebSocket upgrades (101) or other special responses.\n    let is_html = response\n        .headers()\n        .get(header::CONTENT_TYPE)","sourceCodeStart":253,"sourceCodeEnd":289,"githubUrl":"https://github.com/getzola/zola/blob/61d30828217957120309db657950224edf9707e2/src/cmd/serve.rs#L253-L289","documentation":"serve_livereload_js builds an axum/hyper Response with Response::builder().body(...) and .expect panics if response construction fails. With static headers and a static body (LIVE_RELOAD) this only fails if hyper's builder invariants are violated, so in practice it is an invariant assertion.","triggerScenarios":"Visiting /livereload.js during `zola serve` when the http::Response builder rejects the request (invalid header values or builder misuse) — effectively never with the current constants, but any refactor introducing an invalid header value triggers it.","commonSituations":"Patching the handler to add dynamic headers containing illegal characters (newlines, non-ASCII) then serving the dev site.","solutions":["Keep header values static/valid; validate any dynamic header content","Refactor to return Result<Response, Infallible>-style handling or use a pre-built response constant","Use Response::from parts construction that cannot fail for fully static responses"],"exampleFix":"// before\nResponse::builder()\n    .header(header::CONTENT_TYPE, \"text/javascript\")\n    .header(header::ACCESS_CONTROL_ALLOW_ORIGIN, \"*\")\n    .status(StatusCode::OK)\n    .body(Body::from(LIVE_RELOAD))\n    .expect(\"Could not build livereload.js response\")\n// after\nlet mut response = Response::new(Body::from(LIVE_RELOAD));\nresponse.headers_mut().insert(header::CONTENT_TYPE, HeaderValue::from_static(\"text/javascript\"));\nresponse.headers_mut().insert(header::ACCESS_CONTROL_ALLOW_ORIGIN, HeaderValue::from_static(\"*\"));\nresponse","handlingStrategy":"fallback","validationCode":"// assert header values are valid at startup\nlet _ = http::HeaderValue::from_static(\"text/javascript\");\nlet _ = http::HeaderValue::from_static(\"*\");","typeGuard":null,"tryCatchPattern":"match Response::builder()\n    .header(header::CONTENT_TYPE, \"text/javascript\")\n    .header(header::ACCESS_CONTROL_ALLOW_ORIGIN, \"*\")\n    .status(StatusCode::OK)\n    .body(Body::from(LIVE_RELOAD))\n{\n    Ok(resp) => resp,\n    Err(e) => {\n        eprintln!(\"livereload response build failed: {}\", e);\n        StatusCode::INTERNAL_SERVER_ERROR.into_response()\n    }\n}","preventionTips":["Keep static response headers as from_static constants","Never interpolate untrusted strings into header values","Return 500 instead of panicking in dev-server handlers"],"tags":["rust","axum","http","panic","dev-server"],"backgroundTag":"http-response-build-failure","analyzedSha":"61d30828217957120309db657950224edf9707e2","analyzedAt":"2026-09-03T14:39:09.727Z","contentChangedAt":"2026-09-03T14:39:09.727Z","schemaVersion":2},"datasetVersion":"2026-09-10T17:17:09.494Z"}