gravitational/teleport · error

failed to create decoder

Error message

failed to create decoder

What it means

New in lib/srv/desktop/rdp/decoder/decoder.go returns 'failed to create decoder' when the cgo call to construct the native RDP decoder returns a nil pointer. The decoder is created with dimensions, pixel format and channel IDs; a nil native handle means the underlying FreeRDP/decoder initialization failed. Called from handleServerHello, this aborts the RDP/ desktop playback connection.

Source

Thrown at lib/srv/desktop/rdp/decoder/decoder.go:108

type Decoder struct {
	ptr *C.RdpDecoder
}

func New(width, height uint16, opts ...Option) (*Decoder, error) {
	var config decoderConfig
	for _, opt := range opts {
		opt(&config)
	}

	ptr := C.rdp_decoder_new(
		C.uint16_t(width),
		C.uint16_t(height),
		C.uint16_t(config.ioChannelID),
		C.uint16_t(config.userChannelID),
	)
	if ptr == nil {
		return nil, errors.New("failed to create decoder")
	}

	return &Decoder{ptr: ptr}, nil
}

func (d *Decoder) Release() {
	if d.ptr == nil {
		return
	}
	C.rdp_decoder_free(d.ptr)
	d.ptr = nil
}

func (d *Decoder) Resize(width, height uint16) {
	if d.ptr == nil {
		return
	}

View on GitHub (pinned to 1283425b60)

Solutions

  1. Update/rebuild Teleport so the bundled native RDP decoder matches the installed platform libraries
  2. Inspect the capture/server hello for zero or absurd width/height values
  3. Reproduce with the desktop RDP playback tooling and check cgo/native library errors in stderr
  4. Ensure the host has enough memory and the correct shared libraries (ldd) available
Defensive patterns

Strategy: validation

Validate before calling

// validate dimensions before constructing the decoder
if width == 0 || height == 0 {
  return errors.New("refusing to create decoder with empty dimensions")
}
// ensure native libs resolve
if out, err := exec.Command("ldd", decoderLibPath).CombinedOutput(); err != nil {
  return fmt.Errorf("native decoder libs unresolved: %s", out)
}

Type guard

func decoderReady(d *rdpdecoder.Decoder) bool {
  return d != nil
}

Try / catch

dec, err := rdpdecoder.New(w, h, cfg)
if err != nil {
  return fmt.Errorf("rdp decoder unavailable: %w", err)
}
// only then use dec for playback

Prevention

When it happens

Trigger: handleServerHello processes the RDP server hello and calls New with the negotiated width/height, io/user channel IDs; the C decoder allocation fails (invalid dimensions, failed native init, or memory/allocation failure).

Common situations: Recording/playback of desktop sessions where the native decoder library is missing or incompatible (version mismatch of bundled FreeRDP), zero/negative negotiated dimensions from a malformed capture, or constrained memory on the host running playback.

Related errors


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