labstack/echo · error
%s is missing scheme or host: %s
Error message
%s is missing scheme or host: %s
What it means
Returned by validateOrigin() (util.go:124) when an origin parses successfully but is missing either Scheme or Host. Echo requires origins to be fully qualified 'scheme://host' values so they can be matched exactly. The '%s' is the context label, the trailing '%s' is the offending origin.
Source
Thrown at middleware/util.go:124
}
}
func validateOrigins(origins []string, what string) error {
for _, o := range origins {
if err := validateOrigin(o, what); err != nil {
return err
}
}
return nil
}
func validateOrigin(origin string, what string) error {
u, err := url.Parse(origin)
if err != nil {
return fmt.Errorf("can not parse %s: %w", what, err)
}
if u.Scheme == "" || u.Host == "" {
return fmt.Errorf("%s is missing scheme or host: %s", what, origin)
}
if u.Path != "" || u.RawQuery != "" || u.Fragment != "" {
return fmt.Errorf("%s can not have path, query, and fragments: %s", what, origin)
}
return nil
}
View on GitHub (pinned to 05489dc173)
Solutions
- Prefix every origin with a scheme: 'http://localhost:3000' or 'https://example.com'.
- For development, include both http and https variants explicitly.
- Validate origins programmatically before passing to the middleware.
Example fix
// before
cfg := middleware.CORSConfig{AllowOrigins: []string{"localhost:3000", "example.com"}}
// after
cfg := middleware.CORSConfig{AllowOrigins: []string{"http://localhost:3000", "https://example.com"}} Defensive patterns
Strategy: validation
Validate before calling
func requireSchemeHost(origins []string) error {
for _, o := range origins {
u, err := url.Parse(o)
if err != nil { return err }
if u.Scheme == "" || u.Host == "" {
return fmt.Errorf("origin %q missing scheme or host", o)
}
}
return nil
} Prevention
- Always write origins as scheme://host[:port].
- Validate scheme+host presence programmatically before middleware construction.
- Document the required origin format for ops teams managing config.
When it happens
Trigger: Configuring CORS AllowOrigins or CSRF TrustedOrigins with entries like 'localhost:8080' (no scheme), 'example.com' (no scheme), or '/path' (no scheme/host). url.Parse accepts these but u.Scheme/u.Host end up empty.
Common situations: Developers writing 'localhost:3000' instead of 'http://localhost:3000'; configs using bare hostnames; mixing up origin format with Host header format.
Related errors
- can not parse %s: %w
- %s can not have path, query, and fragments: %s
- at least one AllowOrigins is required or UnsafeAllowOriginFu
- timeout must be set
- * as allowed origin and AllowCredentials=true is insecure an
AI-assisted analysis of labstack/echo@05489dc173 (2026-08-04).
Data as JSON: /data/errors/7872b48b12442cad.json.
Report an issue: GitHub.