seanmonstar/warp · error
missing scheme
Error message
missing scheme
What it means
IntoOrigin for &str splits the input on '://' and expects both a scheme and a remainder, panicking with 'missing scheme' otherwise. So cors().allow_origins(&["example.com"]) (no scheme) panics during filter construction.
Solutions
- Always include the scheme: "https://example.com" instead of "example.com"
- Preprocess config origins to prepend "https://" when the scheme is absent (if that matches intent)
- Validate origins at config load time and fail fast with a clear message
Example fix
// before
warp::cors().allow_origin("example.com")
// after
warp::cors().allow_origin("https://example.com") Defensive patterns
Strategy: validation
Validate before calling
fn has_scheme(origin: &str) -> bool { origin.contains("://") }
for o in origins { assert!(has_scheme(o), "origin '{}' missing scheme", o); } Type guard
fn as_origin(s: &str) -> Option<String> { s.contains("://").then(|| s.to_string()) } Prevention
- Always write origins as scheme://host (https://example.com)
- Normalize bare hostnames from config by prepending a scheme when intentional
- Fail fast at config load with a clear message for scheme-less origins
When it happens
Trigger: Calling allow_origins/allow_origin with an origin string lacking '://', e.g. "example.com", "localhost:8080" — splitn yields only one part and the second expect fires.
Common situations: Writing hosts from config without the https:// prefix; assuming bare hostnames are acceptable origins; migrating configs from other CORS libraries that accept bare hosts.
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 seanmonstar/warp@ff34d7213e (2026-09-09).
Data as JSON: /api/errors/6c97ee684af45145.
Report an issue: GitHub.
Appendix: source
Thrown at src/filters/cors.rs:617
fn seconds(self) -> u64 {
self.into()
}
}
impl Seconds for ::std::time::Duration {
fn seconds(self) -> u64 {
self.as_secs()
}
}
pub trait IntoOrigin {
fn into_origin(self) -> Origin;
}
impl<'a> IntoOrigin for &'a str {
fn into_origin(self) -> Origin {
let mut parts = self.splitn(2, "://");
let scheme = parts.next().expect("missing scheme");
let rest = parts.next().expect("missing scheme");
Origin::try_from_parts(scheme, rest, None).expect("invalid Origin")
}
}
}
View on GitHub (pinned to ff34d7213e)