fatedier/frp · error
message frame payload too short
Error message
message frame payload too short
What it means
DecodeV2MessageFrame rejects a message frame whose payload is shorter than the mandatory 2-byte big-endian type ID. Every v2 message frame is at least 2 bytes; anything shorter is malformed. The same guard exists in DecodeV2MessageFrameInto and the UDP binary decoder, because the type ID is the dispatch key for the whole v2 message layer.
Solutions
- Build frames with EncodeV2MessageFrame so the type prefix is always written.
- When constructing manually, prepend the ID: binary.BigEndian.AppendUint16(nil, uint16(typeID)).
- Reject short frames before decoding in custom pipelines.
Example fix
// before
f := &wire.Frame{Type: wire.FrameTypeMessage, Payload: []byte(`{}`)}
// after
f, err := msg.EncodeV2MessageFrame(&msg.Ping{}) Defensive patterns
Strategy: validation
Validate before calling
if f.Type != wire.FrameTypeMessage || len(f.Payload) < 2 {
return errors.New("malformed v2 message frame")
} Prevention
- Use EncodeV2MessageFrame for all frame construction.
- Fuzz your encoders against the decoders to catch length bugs early.
When it happens
Trigger: DecodeV2MessageFrame(&wire.Frame{Type: FrameTypeMessage, Payload: []byte{}}) — empty or 1-byte payloads from fuzzing, truncated writes, or hand-built test frames that forgot the type prefix.
Common situations: Unit tests constructing frames manually; fuzzing corpora; a peer interrupted mid-write producing a short final frame.
Related errors
- message frame payload too short
- unexpected frame type
- invalid pool count , must be non-negative
- unexpected frame type
- unsupported wire protocol
AI-assisted analysis of fatedier/frp@6c8a8d0a97 (2026-08-15).
Data as JSON: /api/errors/12ae3125691796d5.
Report an issue: GitHub.
Appendix: source
Thrown at pkg/msg/wire_v2.go:128
return err
}
return DecodeV2MessageFrameInto(f, m)
}
func (rw *V2ReadWriter) WriteMsg(m Message) error {
f, err := EncodeV2MessageFrame(m)
if err != nil {
return err
}
return rw.conn.WriteFrame(f)
}
func DecodeV2MessageFrame(f *wire.Frame) (Message, error) {
if f.Type != wire.FrameTypeMessage {
return nil, fmt.Errorf("unexpected frame type %d, want %d", f.Type, wire.FrameTypeMessage)
}
if len(f.Payload) < 2 {
return nil, fmt.Errorf("message frame payload too short")
}
typeID := binary.BigEndian.Uint16(f.Payload[:2])
t, ok := v2MsgReflectTypeMap[typeID]
if !ok {
return nil, fmt.Errorf("unknown v2 message type %d", typeID)
}
m := reflect.New(t).Interface()
if err := json.Unmarshal(f.Payload[2:], m); err != nil {
return nil, err
}
return m, nil
}
func DecodeV2MessageFrameInto(f *wire.Frame, out Message) error {
if f.Type != wire.FrameTypeMessage {
return fmt.Errorf("unexpected frame type %d, want %d", f.Type, wire.FrameTypeMessage)
}
if len(f.Payload) < 2 {View on GitHub (pinned to 6c8a8d0a97)