tailscale/tailscale · error
derp.Client: failed to receive server key: %v
Error message
derp.Client: failed to receive server key: %v
What it means
derp.NewClient could not receive and validate the server's greeting (server key frame) before sending the client key: recvServerKey failed on read, frame type, greeting magic, or key length. The connection never got past its first frame, so it is unusable.
Source
Thrown at derp/derp_client.go:144
}
func newClient(privateKey key.NodePrivate, nc Conn, brw *bufio.ReadWriter, logf logger.Logf, opt clientOpt) (*Client, error) {
c := &Client{
privateKey: privateKey,
publicKey: privateKey.Public(),
logf: logf,
nc: nc,
br: brw.Reader,
bw: brw.Writer,
meshKey: opt.MeshKey,
canAckPings: opt.CanAckPings,
isProber: opt.IsProber,
appName: opt.AppName,
clock: tstime.StdClock{},
}
if opt.ServerPub.IsZero() {
if err := c.recvServerKey(); err != nil {
return nil, fmt.Errorf("derp.Client: failed to receive server key: %v", err)
}
} else {
c.serverKey = opt.ServerPub
}
if err := c.sendClientKey(); err != nil {
return nil, fmt.Errorf("derp.Client: failed to send client key: %v", err)
}
return c, nil
}
func (c *Client) PublicKey() key.NodePublic { return c.publicKey }
func (c *Client) recvServerKey() error {
var buf [40]byte
t, flen, err := readFrame(c.br, 1<<10, buf[:])
if err == io.ErrShortBuffer {
// For future-proofing, allow server to send more in its greeting.
err = nilView on GitHub (pinned to a7769cbc33)
Solutions
- Probe the endpoint: curl https://host/derp/probe should return "derp"
- Check server-side logs for the accepted-then-failed connection
- Remove middleboxes and verify TLS configuration
Defensive patterns
Strategy: retry
Validate before calling
resp, err := http.Get(derpBase + "/derp/probe")
if err != nil {
return err
}
defer resp.Body.Close()
b, _ := io.ReadAll(resp.Body)
if resp.StatusCode != 200 || strings.TrimSpace(string(b)) != "derp" {
return fmt.Errorf("%s is not a DERP server", derpBase)
} Try / catch
c, err := derp.NewClient(conn, key, opts)
if err != nil && strings.Contains(err.Error(), "failed to receive server key") {
// greeting failed: often transient or wrong endpoint; re-dial with backoff
c, err = redialWithBackoff(conn, key, opts)
} Prevention
- Validate DERP endpoints with /derp/probe before connecting
- Verify TLS certificates and ports; keep proxies from altering the byte stream
When it happens
Trigger: The remote is not a DERP server (for example it returns an HTTP error page); the connection drops immediately after accept; the greeting frame is malformed; TLS interception mangles the bytes.
Common situations: Wrong address or port; DERP server behind a broken proxy; server crashing on accept.
Related errors
- derp.Client: failed to send client key: %v
- bad frame type 0x%X, want 0x%X
- derp.Send: %w
- derp.ForwardPacket: %w
- derp.NotePreferred: %v
AI-assisted analysis of tailscale/tailscale@a7769cbc33 (2026-08-18).
Data as JSON: /api/errors/1b89c37439a96dff.
Report an issue: GitHub.