tailscale/tailscale · error

reading register response: %w

Error message

reading register response: %w

What it means

The 200 response body could not be read to completion: io.ReadAll over a LimitReader failed (control/tsp/register.go:103). The server accepted the request and began replying, then the stream broke: connection reset, TLS error, premature close, or context cancellation during the read.

Source

Thrown at control/tsp/register.go:103

	res, err := nc.Do(req)
	if err != nil {
		return nil, fmt.Errorf("register request: %w", err)
	}
	defer res.Body.Close()

	maxResponseSize := cmp.Or(opts.MaxResponseSize, DefaultMaxMessageSize)

	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. Retry the call; usually transient
  2. If reproducible, correlate with server logs for a crash mid-response
  3. Raise read timeouts on slow links and on intermediaries
Defensive patterns

Strategy: retry

Try / catch

if err != nil {
    if errors.Is(err, io.ErrUnexpectedEOF) || errors.Is(err, context.DeadlineExceeded) {
        // mid-body break: safe to retry the whole request
        resp, err = c.Register(ctx, opts)
    }
}

Prevention

When it happens

Trigger: Server closes the connection mid-response; proxy/LB idle timeout cutting the transfer; ctx canceled while the body streams.

Common situations: Flaky links; aggressive intermediary timeouts; control server crashing while building the registration response.

Related errors


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