EpicGames/lore · error · anyhow::Error
Stream handler factory was not set
Error message
Stream handler factory was not set
What it means
The QuinnConfig builder requires a stream handler factory before build(); it is what decides which ALPN protocols and services the QUIC server can dispatch to. If the builder was never given one via the builder method, build() returns this error rather than constructing a useless server.
Solutions
- Call the stream_handler_factory setter with a configured factory before build()
- Check launch_quinn_server to confirm every builder field is set
- Add a builder-level debug assert or default factory to catch this at compile/early time
Example fix
// before let cfg = QuinnConfigBuilder::new().address(addr).build()?; // after let cfg = QuinnConfigBuilder::new().address(addr).stream_handler_factory(factory).build()?;
Defensive patterns
Strategy: validation
Validate before calling
let cfg = QuinnConfigBuilder::new(); // ensure factory is set before build assert!(builder_has_stream_handler(&cfg), "stream_handler_factory must be set"); let quinn_cfg = cfg.build()?;
Try / catch
match cfg.build() {
Err(e) if e.to_string().contains("Stream handler factory") => panic!("builder misuse: set stream_handler_factory before build"),
r => r?,
} Prevention
- Wrap builder construction in a helper function that always sets the factory
- Use typestate builder APIs where available to make unset fields unbuildable
When it happens
Trigger: Calling QuinnConfigBuilder::build() without first calling the stream_handler_factory setter; typically a coding mistake in launch_quinn_server wiring or a refactor that dropped the setter call.
Common situations: Refactoring server launch code and forgetting the builder step; conditionally skipping handler registration; copying builder code and omitting a line.
Understand the failure class
Background: "Must pass :limit option" / "Missing required option" — required option errors explained — this error's family across 41 libraries.
Related errors
AI-assisted analysis of EpicGames/lore@074eb0b0d1 (2026-09-13).
Data as JSON: /api/errors/3f41226ef0ec05a5.
Report an issue: GitHub.
Appendix: source
Thrown at lore-server/src/quic/quinn/config.rs:191
pub fn metrics_frequency(mut self, metric_frequency: Duration) -> Self {
self.metrics_frequency = Some(metric_frequency);
self
}
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,View on GitHub (pinned to 074eb0b0d1)