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
- Upgrade the decoding binary so both ends share the same TDPB message vocabulary
- Use errors.Is(err, tdpb.ErrUnknownMessage) to skip and continue when tolerance is desired (as ReadAll-style helpers do)
- 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
- Keep both protocol endpoints on compatible Teleport versions
- Use errors.Is on the sentinel to skip unknown messages
- Log unknown message type bytes for upgrade planning
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
- failed to fetch MySQL version
- unexpected message type
- message is TDP, not TDPB
- an unknown error has occurred
- proto: CreateAuthenticateChallengeRequest: illegal tag %d (w
AI-assisted analysis of gravitational/teleport@1283425b60 (2026-09-02).
Data as JSON: /api/errors/fa330f73958e83ff.
Report an issue: GitHub.