gravitational/teleport · warning

decoded unknown TDPB message

Error message

decoded unknown TDPB message

What it means

Sentinel error from the TDPB protocol package returned by DecodeStrict/DecodePermissive when the decoded message type is not recognized (an unknown message ID). It indicates a message from a newer/unsupported protocol implementation.

Source

Thrown at lib/srv/desktop/tdp/protocol/tdpb/tdpb.go:40

import (
	"bytes"
	"encoding/binary"
	"errors"
	"io"

	"github.com/gravitational/trace"
	"google.golang.org/protobuf/proto"

	tdpbv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/desktop/v1"
	"github.com/gravitational/teleport/lib/srv/desktop/tdp"
)

// ProtocolName is the identifier for the TDPB protocol.
const ProtocolName = "teleport-tdpb-1.0"

// ErrUnknownMessage is returned when an unknown message is decoded.
var ErrUnknownMessage = errors.New("decoded unknown TDPB message")

// ErrIsTDP is returned when a legacy TDP message is received
// during or after a connection upgrade to TDPB.
var ErrIsTDP = errors.New("message is TDP, not TDPB")

const (
	// We can differentiate between TDP and TDPB messages on the wire
	// by inspecting the first byte received. A non-empty first byte
	// is presumed to be a TDP message, otherwise, TDPB.
	// Since the first byte of a TDPB message is the high 8 bits of its
	// length, we must take care not to allow TDPB messages that
	// meet or exceed length 2^24 (16MiB).
	// Once TDP is fully deprecated we can relax this constraint, although
	// it's unlikely we would ever want messages anywhere near this size.
	maxMessageLength = (1 << 24) - 1
	tdpbHeaderLength = 4 // sizeof(uint32)
)

View on GitHub (pinned to 1283425b60)

Solutions

  1. Upgrade the decoding binary so both ends share the same TDPB message vocabulary
  2. Use errors.Is(err, tdpb.ErrUnknownMessage) to skip and continue when tolerance is desired (as ReadAll-style helpers do)
  3. If unexpected, log the raw message type byte and compare against the TDPB protocol registry

Example fix

// before
msg, err := tdpb.DecodeStrict(rdr)
if err != nil { return err }
// after
msg, err := tdpb.DecodeStrict(rdr)
if errors.Is(err, tdpb.ErrUnknownMessage) { continue }
if err != nil { return trace.Wrap(err) }
Defensive patterns

Strategy: try-catch

Try / catch

msg, err := tdpb.DecodeStrict(rdr)
if errors.Is(err, tdpb.ErrUnknownMessage) {
    continue // skip unsupported message from newer peer
}
if err != nil { return nil, trace.Wrap(err) }

Prevention

When it happens

Trigger: Receiving a TDPB frame whose message type byte does not map to any known message struct — typically a message defined in a newer Teleport version than the decoder.

Common situations: Version skew between Teleport components (newer proxy/desktop service sends messages an older binary can't decode); wire corruption; test code iterating messages uses errors.Is to skip unknown ones.

Related errors


AI-assisted analysis of gravitational/teleport@1283425b60 (2026-09-02). Data as JSON: /api/errors/fa330f73958e83ff. Report an issue: GitHub.