{"record":{"id":"fd469d4449e5468c","repo":"EpicGames/lore","slug":"no-alpns-provided","errorCode":null,"errorMessage":"No alpns provided","messagePattern":"No alpns provided","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"lore-server/src/quic/quinn/config.rs","lineNumber":195,"sourceCode":"\n    pub fn transport_bits_per_second(mut self, bits_per_second: usize) -> Self {\n        self.transport_bits_per_second = Some(bits_per_second);\n        self\n    }\n\n    pub fn transport_rtt(mut self, rtt: usize) -> Self {\n        self.transport_rtt = Some(rtt);\n        self\n    }\n\n    pub fn build(self) -> anyhow::Result<QuinnConfig> {\n        let stream_handler_factory = self\n            .stream_handler_factory\n            .ok_or(anyhow!(\"Stream handler factory was not set\"))?;\n\n        let alpns = stream_handler_factory.supported_protocols();\n        if alpns.is_empty() {\n            return Err(anyhow!(\"No alpns provided\"));\n        };\n\n        // A caller-bound socket is the truth about where this serves; asking it beats trusting an\n        // `address` set alongside it, which could disagree.\n        let address = match &self.socket {\n            Some(socket) => socket.local_addr()?,\n            None => self.address.ok_or(anyhow!(\"Address was not set\"))?,\n        };\n\n        Ok(QuinnConfig {\n            server_metrics_name: self.server_metrics_name,\n            address,\n            socket: self.socket,\n            alpns,\n            cert_file: self.cert_file,\n            pkey_file: self.pkey_file,\n            cert_chain: self.cert_chain,\n            client_cert_verifier: self","sourceCodeStart":177,"sourceCodeEnd":213,"githubUrl":"https://github.com/EpicGames/lore/blob/074eb0b0d1194c997d7cf28b55519e3e197b3e23/lore-server/src/quic/quinn/config.rs#L177-L213","documentation":"A generic validation guard in QuinnConfig::build: the assembled stream handler factory advertises no supported ALPN protocols, so the QUIC server would have nothing to negotiate with clients. It fires when launch_quinn_server builds the config before any protocols have been registered on the factory, meaning server startup configuration is incomplete rather than a runtime connection failure.","triggerScenarios":"build() is called and stream_handler_factory.supported_protocols() returns an empty slice — i.e., a factory that was constructed with no services/protocols registered.","commonSituations":"Constructing a default/empty factory in tests; a registration loop that iterates an empty service list; feature flags disabling all services so nothing registers.","solutions":["Register at least one stream handler/protocol in the factory before building the config","Check whether feature flags or empty service lists left the factory with no registrations","Log factory registrations at startup to verify non-empty ALPNs"],"exampleFix":"// before\nlet factory = StreamHandlerFactory::new(); // no handlers registered\n// after\nlet factory = StreamHandlerFactory::new().register(\"lore/1\", handler);","handlingStrategy":"validation","validationCode":"if factory.supported_protocols().is_empty() {\n    return Err(\"stream handler factory has no registered protocols; register at least one before launch\".into());\n}","typeGuard":"fn has_protocols(f: &dyn StreamHandlerFactory) -> bool {\n    !f.supported_protocols().is_empty()\n}","tryCatchPattern":"match cfg.build() {\n    Err(e) if e.to_string().contains(\"No alpns\") => eprintln!(\"register handlers before building QUIC config\"),\n    r => r?,\n}","preventionTips":["Register handlers immediately after constructing the factory","Log registered ALPNs at startup and fail fast if empty","Watch for feature flags that can silently unregister all services"],"tags":["rust","quic","alpn","configuration"],"backgroundTag":"empty-required-field","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"}