{"id":"effd94a874f157ac","repo":"seanmonstar/reqwest","slug":"error-upgrading-connection","errorCode":null,"errorMessage":"error upgrading connection","messagePattern":"error upgrading connection","errorType":"exception","errorClass":"reqwest::Error","httpStatus":null,"severity":"error","filePath":"src/error.rs","lineNumber":402,"sourceCode":"    .with_url(url)\n}\n\npub(crate) fn url_bad_scheme(url: Url) -> Error {\n    Error::new(Kind::Builder, Some(BadScheme)).with_url(url)\n}\n\npub(crate) fn url_invalid_uri(url: Url) -> Error {\n    Error::new(Kind::Builder, Some(\"Parsed Url is not a valid Uri\")).with_url(url)\n}\n\nif_wasm! {\n    pub(crate) fn wasm(js_val: wasm_bindgen::JsValue) -> BoxError {\n        format!(\"{js_val:?}\").into()\n    }\n}\n\npub(crate) fn upgrade<E: Into<BoxError>>(e: E) -> Error {\n    Error::new(Kind::Upgrade, Some(e))\n}\n\n// io::Error helpers\n\n#[allow(unused)]\npub(crate) fn decode_io(e: io::Error) -> Error {\n    if e.get_ref().map(|r| r.is::<Error>()).unwrap_or(false) {\n        *e.into_inner()\n            .expect(\"io::Error::get_ref was Some(_)\")\n            .downcast::<Error>()\n            .expect(\"StdError::is() was true\")\n    } else {\n        decode(e)\n    }\n}\n\n// internal Error \"sources\"\n","sourceCodeStart":384,"sourceCodeEnd":420,"githubUrl":"https://github.com/seanmonstar/reqwest/blob/17e9bcb51c46edebfb6f5f2f5184b51dac4b3a7d/src/error.rs#L384-L420","documentation":"The `Kind::Upgrade` error from `error::upgrade(...)` (error.rs:401-403). It is returned by `Response::upgrade()` (upgrade.rs:69-74) when the underlying `hyper::upgrade::on(...)` future resolves to an error — i.e. the connection could not be switched to a tunneled protocol.","triggerScenarios":"Calling `resp.upgrade().await` on a response that was not actually a 101 Switching Protocols (or 200 with agreed upgrade), or where the peer never sent the expected upgrade bytes. Common for WebSocket-style handshakes where the server rejected the upgrade.","commonSituations":"Trying to `.upgrade()` a normal 200 response; server replied 426/400 to a WebSocket handshake; missing `Connection: Upgrade` / `Upgrade:` headers; proxy stripping upgrade headers.","solutions":["Only call `.upgrade()` after confirming `resp.status() == 101` and that the server agreed to the protocol in its `Upgrade` header.","Use a dedicated WebSocket crate (`tungstenite`) on top of reqwest rather than hand-rolling upgrades.","Inspect `e.source()` for the hyper upgrade error to see why the oneshot channel never received the upgraded IO."],"exampleFix":"// before\nlet upgraded = resp.upgrade().await?; // fails: not actually a 101\n\n// after\nif resp.status() != 101 {\n    anyhow::bail!(\"expected 101 Switching Protocols, got {}\", resp.status());\n}\nif !resp.headers().get(\"upgrade\").map(|v| v == \"websocket\").unwrap_or(false) {\n    anyhow::bail!(\"server did not agree to upgrade\");\n}\nlet upgraded = resp.upgrade().await?;","handlingStrategy":"validation","validationCode":"fn is_upgradable(resp: &reqwest::Response, proto: &str) -> bool {\n    resp.status() == 101\n        && resp.headers().get(\"upgrade\")\n            .map(|v| v.to_str().map(|s| s.eq_ignore_ascii_case(proto)).unwrap_or(false))\n            .unwrap_or(false)\n}\n// guard before .upgrade()\nif !is_upgradable(&resp, \"websocket\") { return Err(anyhow!(\"not a 101 upgrade\")); }\n","typeGuard":"fn is_upgrade_error(e: &reqwest::Error) -> bool { e.is_upgrade() }\n","tryCatchPattern":"let upgraded = match resp.upgrade().await {\n    Ok(u) => u,\n    Err(e) if e.is_upgrade() => return Err(anyhow!(\"upgrade failed: {}\",\n        e.source().map(|s| s.to_string()).unwrap_or_default())),\n    Err(e) => return Err(e.into()),\n};","preventionTips":["Confirm status==101 and the agreed Upgrade header before calling .upgrade().","Prefer a dedicated WebSocket client over hand-rolled reqwest upgrades.","Ensure proxies preserve Connection/Upgrade headers in both directions."],"tags":["upgrade","websocket","connection","http"],"analyzedSha":"17e9bcb51c46edebfb6f5f2f5184b51dac4b3a7d","analyzedAt":"2026-08-06T01:23:05.134Z","schemaVersion":2}