cloudflare/cloudflared · error
invalid protocol selected: %s
Error message
invalid protocol selected: %s
What it means
serveConnection switches on the negotiated transport protocol (QUIC, HTTP2, ...). If the protocol value is anything else — a corrupted config, an unknown future enum, or a programmer error — the default branch rejects it as 'invalid protocol selected: %s' as unrecoverable, since retrying with the same invalid protocol cannot succeed.
Source
Thrown at supervisor/tunnel.go:499
// Rebuild the connection options with the local address now that the
// edge socket is established.
// nolint: gosec
connOptions := e.config.connectionOptions(edgeConn.LocalAddr().String(), uint8(backoff.Retries()))
// nolint: zerologlint
connOptions.LogFields(connLog.Logger().Debug().Uint8(connection.LogFieldConnIndex, connIndex)).Msgf("Tunnel connection options")
if err := e.serveHTTP2(
ctx,
connLog,
edgeConn,
connOptions,
controlStream,
connIndex,
); err != nil {
return err, false
}
default:
return fmt.Errorf("invalid protocol selected: %s", protocol), false
}
return
}
type unrecoverableError struct {
err error
}
func (r unrecoverableError) Error() string {
return r.err.Error()
}
func (e *EdgeTunnelServer) serveHTTP2(
ctx context.Context,
connLog *ConnAwareLogger,
tlsServerConn net.Conn,
connOptions *client.ConnectionOptionsSnapshot,
controlStreamHandler connection.ControlStreamHandler,View on GitHub (pinned to 2253eeeb25)
Solutions
- Check the --protocol flag and config file: valid values are quic, http2, or auto.
- Remove or fix the invalid protocol entry and re-run with `--protocol auto` to let cloudflared negotiate.
- Upgrade cloudflared if the edge is assigning a protocol your binary predates.
- Validate the tunnel config JSON/YAML for stray or renamed fields under protocol selection.
Example fix
// before cloudflared tunnel run --protocol h3 my-tunnel // after cloudflared tunnel run --protocol auto my-tunnel
Defensive patterns
Strategy: try-catch
Validate before calling
// at startup: verify the base config exists before serving
if e.config.EdgeTLSConfigs[connection.HTTP2] == nil {
return errors.New("HTTP2 edge TLS config was not initialized")
} Try / catch
tlsConfig, err := cfdcrypto.TLSConfigWithCurvePreferences(e.config.EdgeTLSConfigs[protocol], pqMode)
if err != nil {
log.Error().Err(err).Msg("TLS config build failed; will retry")
return fmt.Errorf("could not create TLS configuration: %w", err), true
} Prevention
- Fix any CA-pool/credential initialization errors reported at startup before debugging this error.
- Keep cloudflared current when using --post-quantum.
- Avoid pinning --protocol http2 if the environment keeps failing; allow auto fallback to QUIC.
When it happens
Trigger: The resolved protocol from config/CLI (--protocol) or edge negotiation holds a value outside the known set (e.g. hand-edited config file with `protocol: tcp`, stale flag parsing, or a binary older than a newly introduced protocol returned by remote config).
Common situations: Typoed --protocol flag value; stale/foreign config file entries under tunnel credentials/remote configuration; mixed-version environments where edge assigns a protocol this binary does not know.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- No configuration file was found. Please create one, or use t
- ErrNoIngressRulesCLI
- Did not receive final destination from client. The --destina
- configuration file %s must contain entries for the tunnel to
- possible conflicting configuration in %[1]s and %[2]s. Eithe
AI-assisted analysis of cloudflare/cloudflared@2253eeeb25 (2026-09-06).
Data as JSON: /api/errors/68401507a8a2e624.
Report an issue: GitHub.