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 file

View on GitHub (pinned to 2253eeeb25)

Solutions

  1. Ensure the listener includes a full scheme, e.g. `listener: ws://localhost:8080` or `http://127.0.0.1:8080`.
  2. Run `cloudflared access tcp --help` / check docs for expected forwarder URL format and correct the config key name.
  3. Test the URL with `url.Parse` semantics or curl to confirm it is well-formed before rerunning.
  4. 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

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.