{"record":{"id":"19b32abd6a8ea082","repo":"EpicGames/lore","slug":"failed-to-decode-protocol-e","errorCode":null,"errorMessage":"Failed to decode protocol: {e:?}","messagePattern":"Failed to decode protocol: (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"lore-server/src/quic/quinn/quinn_server.rs","lineNumber":261,"sourceCode":"                .in_current_span(),\n            )\n        );\n    }\n\n    Ok(())\n}\n\nfn get_protocol(connection: &quinn::Connection) -> Result<String, anyhow::Error> {\n    let handshake_data = connection\n        .handshake_data()\n        .and_then(|h| h.downcast::<HandshakeData>().ok())\n        .ok_or(anyhow!(\"No handshake data\"))?;\n\n    handshake_data\n        .protocol\n        .map(String::from_utf8)\n        .transpose()\n        .map_err(|e| anyhow!(\"Failed to decode protocol: {e:?}\"))?\n        .ok_or(anyhow!(\"No protocol found on request\"))\n}\n\n#[tracing::instrument(\n    name = \"urc-quic\",\n    skip_all,\n    fields(connection_id, protocol, correlation_id, repository_id)\n)]\nasync fn handle_conn(\n    conn: quinn::Incoming,\n    monitor: TaskMonitor,\n    connection_metrics_interval: Duration,\n    stream_handler_factory: Arc<Box<dyn StreamHandlerFactory>>,\n) -> anyhow::Result<()> {\n    let connection = conn.await?;\n\n    let protocol = get_protocol(&connection)?;\n","sourceCodeStart":243,"sourceCodeEnd":279,"githubUrl":"https://github.com/EpicGames/lore/blob/074eb0b0d1194c997d7cf28b55519e3e197b3e23/lore-server/src/quic/quinn/quinn_server.rs#L243-L279","documentation":"The negotiated ALPN protocol bytes from the TLS handshake must be valid UTF-8; quinn stores them as raw bytes. If they are not, String::from_utf8 fails and get_protocol wraps the error with this message.","triggerScenarios":"A client (or middlebox) sends an ALPN value containing invalid UTF-8 bytes; the protocol field decodes as Some(bytes) but from_utf8 returns Err.","commonSituations":"Malicious or buggy clients probing the server; custom ALPN strings with non-ASCII characters; corrupted handshake data.","solutions":["Fix the client to send ASCII/UTF-8 ALPN values","Use String::from_utf8_lossy or bytes::String where possible to tolerate invalid input","Keep ALPN registrations to standard ASCII protocol names"],"exampleFix":"// before\n.map(String::from_utf8)\n.transpose()\n.map_err(|e| anyhow!(\"Failed to decode protocol: {e:?}\"))?\n// after\n.map(|b| String::from_utf8_lossy(&b).into_owned())","handlingStrategy":"validation","validationCode":"// validate ALPN values at registration time\nfn valid_alpn(p: &[u8]) -> bool { std::str::from_utf8(p).map(|s| s.is_ascii()).unwrap_or(false) }","typeGuard":null,"tryCatchPattern":"match get_protocol(&connection) {\n    Err(e) if e.to_string().contains(\"Failed to decode protocol\") => { warn!(\"invalid UTF-8 ALPN from client\"); return Ok(()); }\n    r => r?,\n}","preventionTips":["Only register ASCII ALPN protocol names","Consider from_utf8_lossy for tolerant decoding","Reject non-ASCII ALPNs at TLS config build time"],"tags":["rust","quic","alpn","utf8"],"backgroundTag":"invalid-argument-format","analyzedSha":"074eb0b0d1194c997d7cf28b55519e3e197b3e23","analyzedAt":"2026-09-13T09:00:57.509Z","contentChangedAt":"2026-09-13T09:00:57.509Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}