tailscale/tailscale · error

decoding register response: %w

Error message

decoding register response: %w

What it means

The 200 body is not valid JSON for tailcfg.RegisterResponse: json.Unmarshal failed after transport and size checks passed. The content is wrong rather than unreachable: typically an HTML error page, an empty body, or output from an incompatible server version.

Source

Thrown at control/tsp/register.go:110

	if res.StatusCode != 200 {
		msg, _ := io.ReadAll(io.LimitReader(res.Body, maxResponseSize))
		return nil, fmt.Errorf("register request: http %d: %.200s",
			res.StatusCode, strings.TrimSpace(string(msg)))
	}

	// Read up to maxResponseSize+1 so we can distinguish "exactly at cap" from
	// "over the cap" rather than relying on a truncated json parse error.
	data, err := io.ReadAll(io.LimitReader(res.Body, maxResponseSize+1))
	if err != nil {
		return nil, fmt.Errorf("reading register response: %w", err)
	}
	if int64(len(data)) > maxResponseSize {
		return nil, fmt.Errorf("register response exceeds max %d", maxResponseSize)
	}
	var resp tailcfg.RegisterResponse
	if err := json.Unmarshal(data, &resp); err != nil {
		return nil, fmt.Errorf("decoding register response: %w", err)
	}
	if resp.Error != "" {
		return nil, fmt.Errorf("register: %s", resp.Error)
	}
	return &resp, nil
}

View on GitHub (pinned to 6e0912f979)

Solutions

  1. Log the raw body before Unmarshal in a debug build to see what actually arrived
  2. Remove or fix middleboxes between client and control server
  3. Verify the server implements the register protocol version this client expects
Defensive patterns

Strategy: try-catch

Try / catch

if err != nil {
    var syn *json.SyntaxError
    if errors.As(err, &syn) {
        // body was not JSON: inspect what the server or proxy actually returned
    }
}

Prevention

When it happens

Trigger: A proxy or CDN intercepting and rewriting the response; a control server speaking a different schema; a body mangled or truncated in transit.

Common situations: TLS-intercepting middleboxes; ingress returning 200 with an error page; version skew with a forked control server.

Related errors


AI-assisted analysis of tailscale/tailscale@6e0912f979 (2026-08-18). Data as JSON: /api/errors/bc482537cb416bdb. Report an issue: GitHub.