nikivdev/code · error · anyhow::Error

Host must end with .localhost

Error message

Host must end with .localhost

What it means

All domain routes live under the .localhost TLD so the local proxy can resolve them. After other checks pass, normalize_host rejects any host that does not end with ".localhost".

Source

Thrown at src/domains.rs:284

    Ok(())
}

fn normalize_host(raw: &str) -> Result<String> {
    let mut host = raw.trim().to_ascii_lowercase();
    if let Some(stripped) = host.strip_prefix("http://") {
        host = stripped.to_string();
    } else if let Some(stripped) = host.strip_prefix("https://") {
        host = stripped.to_string();
    }
    host = host.trim_end_matches('/').to_string();
    if host.is_empty() {
        bail!("Host is empty");
    }
    if host.contains('/') || host.contains(':') || host.contains(char::is_whitespace) {
        bail!("Host must be a hostname like linsa.localhost");
    }
    if !host.ends_with(".localhost") {
        bail!("Host must end with .localhost");
    }
    if host == ".localhost" || host == "localhost" {
        bail!("Host must include a subdomain (for example: linsa.localhost)");
    }
    Ok(host)
}

fn normalize_target(raw: &str) -> Result<String> {
    let mut target = raw.trim().to_string();
    if let Some(stripped) = target.strip_prefix("http://") {
        target = stripped.to_string();
    } else if let Some(stripped) = target.strip_prefix("https://") {
        target = stripped.to_string();
    }
    target = target.trim_end_matches('/').to_string();
    if target.is_empty() {
        bail!("Target is empty");
    }

View on GitHub (pinned to a747e741ae)

Solutions

  1. Use a <subdomain>.localhost host, e.g. linsa.localhost
  2. Adjust any scripts/configs that pass non-.localhost hosts
  3. Configure your browser/resolver to use .localhost for local dev

Example fix

// before
f domains add linsa.dev :3000
// after
f domains add linsa.localhost :3000
Defensive patterns

Strategy: validation

Validate before calling

let h = raw.trim();
if !h.ends_with(".localhost") {
    return Err(format!("{h} must end with .localhost"));
}

Type guard

fn is_localhost_host(h: &str) -> bool {
    h.ends_with(".localhost") && h != ".localhost" && h != "localhost"
}

Prevention

When it happens

Trigger: Adding/getting/removing a route with hosts like "linsa.dev", "myapp.com", or "linsa.local".

Common situations: Typing a real production domain by habit, using the older ".local" dev TLD, or forgetting this tool's .localhost convention.

Related errors


AI-assisted analysis of nikivdev/code@a747e741ae (2026-09-01). Data as JSON: /api/errors/c0c8a129cc0e4aaa. Report an issue: GitHub.