bcicen/ctop · error
Wrong frame format
Error message
Wrong frame format
What it means
docker.go's Write parses the Docker attach stream, where each frame has an 8-byte header [STREAM_TYPE,0,0,0,SIZE1..4]. If the first header byte is not one of 0/1/2 (stdin/stdout/stderr), the stream is malformed and wrongFrameFormat is returned. This guards against corrupted or non-standard multiplexed streams.
Source
Thrown at connector/manager/docker.go:38
}
}
// Do not allow to close reader (i.e. /dev/stdin which docker client tries to close after command execution)
type noClosableReader struct {
io.Reader
}
func (w *noClosableReader) Read(p []byte) (n int, err error) {
return w.Reader.Read(p)
}
const (
STDIN = 0
STDOUT = 1
STDERR = 2
)
var wrongFrameFormat = errors.New("Wrong frame format")
// A frame has a Header and a Payload
// Header: [8]byte{STREAM_TYPE, 0, 0, 0, SIZE1, SIZE2, SIZE3, SIZE4}
// STREAM_TYPE can be:
// 0: stdin (is written on stdout)
// 1: stdout
// 2: stderr
// SIZE1, SIZE2, SIZE3, SIZE4 are the four bytes of the uint32 size encoded as big endian.
// But we don't use size, because we don't need to find the end of frame.
type frameWriter struct {
stdout io.Writer
stderr io.Writer
stdin io.Writer
}
func (w *frameWriter) Write(p []byte) (n int, err error) {
// drop initial empty frames
if len(p) == 0 {View on GitHub (pinned to 59f00dd6aa)
Solutions
- Ensure the container/connection was created with TTY disabled so Docker emits the 8-byte multiplexed frame headers
- Validate the first byte of each frame before parsing and skip/resync on unknown stream types
- Check for truncated reads — read the full 8-byte header before dispatching on STREAM_TYPE
Example fix
// before tty: true // raw stream, no frame headers // after tty: false // docker emits [STREAM_TYPE,0,0,0,SIZE...] frames that Write can parse
Defensive patterns
Strategy: validation
Validate before calling
hdr := make([]byte, 8)
if _, err := io.ReadFull(r, hdr); err != nil { return err }
if hdr[0] > 2 { return fmt.Errorf("unexpected stream type %d", hdr[0]) } Type guard
func validStreamType(b byte) bool { return b == 0 || b == 1 || b == 2 } Try / catch
n, err := w.Write(p)
if errors.Is(err, manager.wrongFrameFormat) || err.Error() == "Wrong frame format" {
// resync stream or recreate connection with tty disabled
} Prevention
- Create containers/exec with TTY disabled so frames are multiplexed
- Always read the full 8-byte header before dispatching
- Validate STREAM_TYPE byte before use
When it happens
Trigger: Reading from a Docker container attach/exec stream whose first header byte is not 0, 1, or 2 (e.g. tty-mode output without the multiplexed protocol, or a truncated/corrupt header).
Common situations: Attaching to a container started with TTY enabled (raw stream, no frame headers); parsing a non-Docker or hijacked connection; reading a partial frame after a network interruption.
Related errors
AI-assisted analysis of bcicen/ctop@59f00dd6aa (2026-09-02).
Data as JSON: /api/errors/8b48d846386a6493.
Report an issue: GitHub.