EpicGames/lore · error · anyhow::Error
No alpns provided
Error message
No alpns provided
What it means
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.
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
Example fix
// before
let factory = StreamHandlerFactory::new(); // no handlers registered
// after
let factory = StreamHandlerFactory::new().register("lore/1", handler); Defensive patterns
Strategy: validation
Validate before calling
if factory.supported_protocols().is_empty() {
return Err("stream handler factory has no registered protocols; register at least one before launch".into());
} Type guard
fn has_protocols(f: &dyn StreamHandlerFactory) -> bool {
!f.supported_protocols().is_empty()
} Try / catch
match cfg.build() {
Err(e) if e.to_string().contains("No alpns") => eprintln!("register handlers before building QUIC config"),
r => r?,
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: Constructing a default/empty factory in tests; a registration loop that iterates an empty service list; feature flags disabling all services so nothing registers.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- Failed to decode protocol
- No protocol found on request
- Received connection for unsupported protocol
- Missing QUIC certificate config
- Missing cert chain
AI-assisted analysis of EpicGames/lore@074eb0b0d1 (2026-09-13).
Data as JSON: /api/errors/fd469d4449e5468c.
Report an issue: GitHub.
Appendix: source
Thrown at lore-server/src/quic/quinn/config.rs:195
pub fn transport_bits_per_second(mut self, bits_per_second: usize) -> Self {
self.transport_bits_per_second = Some(bits_per_second);
self
}
pub fn transport_rtt(mut self, rtt: usize) -> Self {
self.transport_rtt = Some(rtt);
self
}
pub fn build(self) -> anyhow::Result<QuinnConfig> {
let stream_handler_factory = self
.stream_handler_factory
.ok_or(anyhow!("Stream handler factory was not set"))?;
let alpns = stream_handler_factory.supported_protocols();
if alpns.is_empty() {
return Err(anyhow!("No alpns provided"));
};
// A caller-bound socket is the truth about where this serves; asking it beats trusting an
// `address` set alongside it, which could disagree.
let address = match &self.socket {
Some(socket) => socket.local_addr()?,
None => self.address.ok_or(anyhow!("Address was not set"))?,
};
Ok(QuinnConfig {
server_metrics_name: self.server_metrics_name,
address,
socket: self.socket,
alpns,
cert_file: self.cert_file,
pkey_file: self.pkey_file,
cert_chain: self.cert_chain,
client_cert_verifier: selfView on GitHub (pinned to 074eb0b0d1)