cloudflare/cloudflared · error

failed to build quick tunnel request body

Error message

failed to build quick tunnel request body

What it means

RunQuickTunnel builds the JSON request body for registering a free trycloudflare.com quick tunnel via buildQuickTunnelRequestBody. If marshaling that body fails, the error is wrapped as 'failed to build quick tunnel request body' and quick-tunnel startup aborts before any HTTP request is made.

Source

Thrown at cmd/cloudflared/tunnel/quick_tunnel.go:61

func RunQuickTunnel(sc *subcommandContext) error {
	sc.log.Info().Msg(disclaimer)
	sc.log.Info().Msg("Requesting new quick Tunnel on trycloudflare.com...")

	// TODO(TUN-10798): register the --allowed-mail flag so this path becomes reachable.
	allowedMail := sc.c.StringSlice(flags.AllowedMail)
	isProtected := len(allowedMail) > 0

	client := http.Client{
		Transport: &http.Transport{
			TLSHandshakeTimeout:   httpTimeout,
			ResponseHeaderTimeout: httpTimeout,
		},
		Timeout: httpTimeout,
	}

	reqBody, err := buildQuickTunnelRequestBody(isProtected)
	if err != nil {
		return errors.Wrap(err, "failed to build quick tunnel request body")
	}

	req, err := http.NewRequest(http.MethodPost, fmt.Sprintf("%s/tunnel", sc.c.String("quick-service")), bytes.NewReader(reqBody))
	if err != nil {
		return errors.Wrap(err, "failed to build quick tunnel request")
	}
	req.Header.Add("Content-Type", "application/json")
	req.Header.Add("User-Agent", buildInfo.UserAgent())

	resp, err := client.Do(req)
	if err != nil {
		return errors.Wrap(err, "failed to request quick Tunnel")
	}
	defer func() { _ = resp.Body.Close() }()

	// This will read the entire response into memory so we can print it in case of error
	respBody, err := io.ReadAll(resp.Body)
	if err != nil {

View on GitHub (pinned to 2253eeeb25)

Solutions

  1. Retry `cloudflared tunnel --url http://localhost:PORT` — transient/internal failures usually don't recur.
  2. Upgrade cloudflared to the latest release to rule out a build/version bug.
  3. Check the wrapped inner error (json marshal detail) for the offending field.
  4. Use a named tunnel with credentials instead of quick tunnels if the issue persists.

Example fix

// before
cloudflared tunnel --url http://localhost:8080  # old build, body marshal fails
// after
# upgrade then retry
cloudflared update
cloudflared tunnel --url http://localhost:8080
Defensive patterns

Strategy: try-catch

Try / catch

reqBody, err := buildQuickTunnelRequestBody(isProtected)
if err != nil {
	return errors.Wrap(err, "failed to build quick tunnel request body")
}

Prevention

When it happens

Trigger: Running `cloudflared tunnel --url ...` (quick tunnel mode) when buildQuickTunnelRequestBody cannot serialize the registration payload (JSON marshal failure of the request structure).

Common situations: Rare; typically triggered by internal issues such as unsupported values in the request payload or corrupted binary/build; most users hit this on old or mismatched cloudflared builds.

Understand the failure class

Background: json.Marshal / "failed to marshal" errors in Go: why "unsupported type" happens and how to fix it — this error's family across 22 libraries.

Related errors


AI-assisted analysis of cloudflare/cloudflared@2253eeeb25 (2026-09-06). Data as JSON: /api/errors/c170250ac28c20ad. Report an issue: GitHub.