{"record":{"id":"861add8fb7b4d3dc","repo":"n0-computer/iroh","slug":"invalidheader","errorCode":"InvalidHeader","errorMessage":"invalid header value for {header}: {details}","messagePattern":"invalid header value for (.+?): (.+?)","errorType":"http","errorClass":"RelayUpgradeReqError","httpStatus":null,"severity":"error","filePath":"iroh-relay/src/server/http_server.rs","lineNumber":587,"sourceCode":"        res\n    }\n\n    /// Upgrades the HTTP connection to the relay protocol, runs relay client.\n    fn handle_relay_ws_upgrade(\n        &self,\n        mut req: Request<Incoming>,\n    ) -> Result<Response<BytesBody>, RelayUpgradeReqError> {\n        fn expect_header(\n            req: &Request<Incoming>,\n            header: http::HeaderName,\n        ) -> Result<&HeaderValue, RelayUpgradeReqError> {\n            req.headers()\n                .get(&header)\n                .ok_or_else(|| e!(RelayUpgradeReqError::MissingHeader { header }))\n        }\n\n        let upgrade_header = expect_header(&req, UPGRADE)?;\n        ensure!(\n            upgrade_header == HeaderValue::from_static(WEBSOCKET_UPGRADE_PROTOCOL),\n            RelayUpgradeReqError::InvalidHeader {\n                header: UPGRADE,\n                details: format!(\"value must be {WEBSOCKET_UPGRADE_PROTOCOL}\")\n            }\n        );\n\n        let key = expect_header(&req, SEC_WEBSOCKET_KEY)?.clone();\n        let version = expect_header(&req, SEC_WEBSOCKET_VERSION)?.clone();\n\n        ensure!(\n            version.as_bytes() == SUPPORTED_WEBSOCKET_VERSION.as_bytes(),\n            RelayUpgradeReqError::UnsupportedWebsocketVersion\n        );\n\n        let subprotocols = expect_header(&req, SEC_WEBSOCKET_PROTOCOL)?\n            .to_str()\n            .ok()","sourceCodeStart":569,"sourceCodeEnd":605,"githubUrl":"https://github.com/n0-computer/iroh/blob/2b4de030ce5e0133f272871a76f0c685c63f552a/iroh-relay/src/server/http_server.rs#L569-L605","documentation":"During a relay websocket upgrade, a required HTTP header was present but its value was invalid. The server validates upgrade headers (e.g. the Upgrade header must equal \"websocket\") and returns RelayUpgradeReqError::InvalidHeader when the value does not match the expected static value.","triggerScenarios":"handle_relay_ws_upgrade checks a request header (here UPGRADE) whose value is not the required constant — e.g. Upgrade: h2c, HTTP/2.0, or a modified value, instead of \"websocket\".","commonSituations":"Proxies or gateways rewriting/dropping the Upgrade header, custom HTTP clients not setting the websocket upgrade correctly, using HTTP/2 (where the classic Upgrade handshake doesn't apply), or missing the Connection: Upgrade header pairing.","solutions":["Send Upgrade: websocket (exactly, case per HeaderValue::from_static comparison) on the websocket handshake request.","Check intermediate proxies/load balancers for header rewriting; disable websocket header normalization or pass headers through untouched.","Use a standard websocket client library to perform the handshake instead of a hand-rolled HTTP request.","Ensure HTTP/1.1 is used for the upgrade; HTTP/2 requires extended CONNECT, which this endpoint does not accept."],"exampleFix":"// before: custom request with wrong upgrade value\nlet req = Request::builder()\n    .header(\"Upgrade\", \"WebSocket/1.0\")\n    .header(\"Connection\", \"keep-alive\");\n// after: standard websocket upgrade headers\nlet req = Request::builder()\n    .header(\"Upgrade\", \"websocket\")\n    .header(\"Connection\", \"Upgrade\")\n    .header(\"Sec-WebSocket-Key\", base64_key)\n    .header(\"Sec-WebSocket-Version\", \"13\");","handlingStrategy":"validation","validationCode":"const REQUIRED_UPGRADE: &str = \"websocket\";\nfn upgrade_header_ok(req: &http::Request<impl _>) -> bool {\n    req.headers()\n        .get(http::header::UPGRADE)\n        .and_then(|v| v.to_str().ok())\n        .map(|v| v.eq_ignore_ascii_case(REQUIRED_UPGRADE))\n        .unwrap_or(false)\n}","typeGuard":null,"tryCatchPattern":"match handle_relay_ws_upgrade(req, tunnel_service).await {\n    Err(RelayUpgradeReqError::InvalidHeader { header, details }) => {\n        tracing::debug!(\"bad {header:?} in upgrade: {details}\");\n        Response::builder().status(400).body(\"invalid upgrade headers\")\n    }\n    other => other,\n}","preventionTips":["Use a maintained websocket client library for the handshake","Verify proxies preserve Upgrade and Connection headers verbatim","Perform upgrades over HTTP/1.1, not HTTP/2","Include Sec-WebSocket-Key and Sec-WebSocket-Version: 13 in every request"],"tags":["http","websocket","headers"],"backgroundTag":"invalid-argument-format","analyzedSha":"2b4de030ce5e0133f272871a76f0c685c63f552a","analyzedAt":"2026-09-08T04:26:47.755Z","contentChangedAt":"2026-09-08T04:26:47.755Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}