EpicGames/lore · error · anyhow::Error

Failed to start maintenance HTTP server

Error message

Failed to start maintenance HTTP server: {err}

What it means

serve_maintenance parses "host:port" into a SocketAddr before binding the maintenance HTTP server. If parsing fails (invalid host or port), the failure is wrapped as "Failed to start maintenance HTTP server". The maintenance endpoint never starts.

Solutions

  1. Check the maintenance host/port settings; the port must be a number 0–65535 and the host an IP address.
  2. Use 0.0.0.0 or 127.0.0.1 for the host instead of a DNS name if parsing keeps failing.
  3. Resolve DNS names to IPs outside the config, since SocketAddr::from_str does not do DNS lookup.

Example fix

// before (config)
maintenance_host = "maintenance.internal"  // not parseable as SocketAddr
// after
maintenance_host = "0.0.0.0"
maintenance_port = 9090
Defensive patterns

Strategy: validation

Validate before calling

"127.0.0.1:9090".parse::<std::net::SocketAddr>()
    .map_err(|e| format!("maintenance addr invalid: {e}"))?;

Try / catch

match serve_maintenance(...).await {
    Err(e) if e.to_string().contains("Failed to start maintenance HTTP server") => {
        eprintln!("check maintenance host/port settings: {e}");
        std::process::exit(1);
    }
    other => other?,
}

Prevention

When it happens

Trigger: Calling serve_maintenance with a host that is not an IP/parseable address (e.g. a DNS name with underscores, or empty host) or a port outside 0–65535 / non-numeric.

Common situations: Config uses a hostname where a socket address is expected; port configured as "http" service name; host left empty in YAML; IPv6 zone syntax mistakes.

Understand the failure class

Background: "Invalid URL" errors: why new URL(), URI.parse, and reqwest::Url reject your string — missing scheme, whitespace, and bad path format — this error's family across 39 libraries.

Related errors


AI-assisted analysis of EpicGames/lore@074eb0b0d1 (2026-09-13). Data as JSON: /api/errors/61abea19ba56dd2e. Report an issue: GitHub.

Appendix: source

Thrown at lore-server/src/http/server.rs:242

        )
        .map_err(|err| anyhow!("{} {err}", presign_content_type_field(err.field())))?,
    }))
}

impl LoreHttpServer {
    /// Starts a minimal HTTP server that only serves the `/health_check` endpoint.
    ///
    /// Used during maintenance mode so that load balancers and monitoring systems
    /// can still reach the server. Always returns 200 OK (store health checks are
    /// disabled since the server is intentionally in a reduced state).
    pub async fn serve_maintenance(
        host: String,
        port: i32,
        user_agent_filter: Arc<UserAgentFilter>,
        signal: impl Future<Output = ()> + Send + 'static,
    ) -> Result<()> {
        let addr = SocketAddr::from_str(format!("{host}:{port}").as_str())
            .map_err(|err| anyhow!("Failed to start maintenance HTTP server: {err}"))?;
        info!("Starting Lore maintenance HTTP Server: {}", &addr);

        let health = Arc::new(ServerHealth {
            immutable_store: Weak::<lore_storage::LocalImmutableStore>::new(),
            available: AtomicBool::new(true),
            interval_timeout: None,
            store_health_check: false,
        });

        let app = Router::new()
            .route(
                "/health_check",
                routing::get(health_check::handler).with_state(health),
            )
            .layer(HttpMetricsLayer::new(user_agent_filter))
            .layer(CoreHopLayer);

        let listener = TcpListener::bind(addr)

View on GitHub (pinned to 074eb0b0d1)