cloudflare/cloudflared · error
error validating origin URL
Error message
error validating origin URL
What it means
carrier.StartForwarder validates the forward-configured listener/origin URL with validation.ValidateUrl before opening the websocket forwarder. "error validating origin URL" wraps that failure, meaning the URL string in the config (forwarder.Listener) is missing, malformed, or uses an unsupported scheme. Nothing is sent over the network; this is local configuration validation.
Source
Thrown at cmd/cloudflared/access/carrier.go:31
"github.com/cloudflare/cloudflared/carrier"
"github.com/cloudflare/cloudflared/config"
"github.com/cloudflare/cloudflared/logger"
"github.com/cloudflare/cloudflared/stream"
"github.com/cloudflare/cloudflared/validation"
)
const (
LogFieldHost = "host"
cfAccessClientIDHeader = "Cf-Access-Client-Id"
cfAccessClientSecretHeader = "Cf-Access-Client-Secret"
)
// StartForwarder starts a client side websocket forward
func StartForwarder(forwarder config.Forwarder, shutdown <-chan struct{}, log *zerolog.Logger) error {
validURL, err := validation.ValidateUrl(forwarder.Listener)
if err != nil {
return errors.Wrap(err, "error validating origin URL")
}
// get the headers from the config file and add to the request
headers := make(http.Header)
if forwarder.TokenClientID != "" {
headers.Set(cfAccessClientIDHeader, forwarder.TokenClientID)
}
if forwarder.TokenSecret != "" {
headers.Set(cfAccessClientSecretHeader, forwarder.TokenSecret)
}
headers.Set("User-Agent", userAgent)
carrier.SetBastionDest(headers, forwarder.Destination)
options := &carrier.StartOptions{
OriginURL: forwarder.URL,
Headers: headers, //TODO: TUN-2688 support custom headers from config fileView on GitHub (pinned to 2253eeeb25)
Solutions
- Ensure the listener includes a full scheme, e.g. `listener: ws://localhost:8080` or `http://127.0.0.1:8080`.
- Run `cloudflared access tcp --help` / check docs for expected forwarder URL format and correct the config key name.
- Test the URL with `url.Parse` semantics or curl to confirm it is well-formed before rerunning.
- Check that the right config file is loaded (TUNNEL_CONFIG) so listener isn't empty.
Example fix
// before (config.yml) forwarder: listener: localhost:8080 // after forwarder: listener: ws://localhost:8080
Defensive patterns
Strategy: validation
Validate before calling
u, err := url.Parse(forwarder.Listener)
if err != nil || u.Scheme == "" || u.Host == "" {
return fmt.Errorf("listener must be a full URL with scheme and host, got %q", forwarder.Listener)
} Try / catch
if err := carrier.StartForwarder(forwarder, shutdown, log); err != nil {
log.Err(err).Msgf("forwarder start failed: %+v", err)
return err
} Prevention
- Always include scheme and host in listener URLs (ws:// or http://)
- Keep config keys consistent with docs so listener is not empty
- Sanity-check URLs with url.Parse in tooling before deploy
When it happens
Trigger: Running `cloudflared access ws-forward` (or config forwarder entries) where the listener value is empty, lacks a scheme, has an invalid host/port, or is otherwise unparseable as a URL.
Common situations: Config file forwarder blocks with `listener: localhost:8080` (missing scheme) or typos like `htp://`; empty listener because the config section was misnamed; environment-specific overrides left blank.
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 cloudflare/cloudflared@2253eeeb25 (2026-09-06).
Data as JSON: /api/errors/0fb8f46304b89b44.
Report an issue: GitHub.