larksuite/cli · error
protocol: unknown message type %q
Error message
protocol: unknown message type %q
What it means
protocol.Decode parsed the JSON envelope but its 'type' field does not match any known message type constant (Hello, Event, StatusResponse, Shutdown, SourceStatus), so no target struct exists to unmarshal into. This guards the protocol against version skew and garbage-with-valid-JSON frames.
Source
Thrown at internal/event/adapter/localbus/protocol/codec.go:116
msg = &HelloAck{}
case MsgTypeEvent:
msg = &Event{}
case MsgTypeBye:
msg = &Bye{}
case MsgTypePreShutdownCheck:
msg = &PreShutdownCheck{}
case MsgTypePreShutdownAck:
msg = &PreShutdownAck{}
case MsgTypeStatusQuery:
msg = &StatusQuery{}
case MsgTypeStatusResponse:
msg = &StatusResponse{}
case MsgTypeShutdown:
msg = &Shutdown{}
case MsgTypeSourceStatus:
msg = &SourceStatus{}
default:
return nil, fmt.Errorf("protocol: unknown message type %q", env.Type)
}
if err := json.Unmarshal(line, msg); err != nil {
return nil, fmt.Errorf("protocol decode %s: %w", env.Type, err)
}
return msg, nil
}
View on GitHub (pinned to 7fd6ef3c07)
Solutions
- Log the %q type value from the error and compare against the sender's protocol constants
- Upgrade/downgrade so both bus and client use the same lark-cli version (protocol mismatch is the usual cause)
- Fix the sender to use the exported MsgType* constants instead of string literals
- If forward-compatibility is needed, have the reader ignore unknown types instead of failing the connection
Example fix
// before
conn.Write([]byte(`{"type":"Ping"}`))
// after
protocol.Encode(conn, &protocol.Hello{}) // uses MsgTypeHello constant Defensive patterns
Strategy: type-guard
Validate before calling
func knownType(line []byte) bool {
var env struct{ Type string `json:"type"` }
if json.Unmarshal(line, &env) != nil {
return false
}
switch env.Type {
case protocol.MsgTypeHello, protocol.MsgTypeEvent,
protocol.MsgTypeStatusResponse, protocol.MsgTypeShutdown,
protocol.MsgTypeSourceStatus:
return true
}
return false
} Type guard
func isUnknownTypeError(err error) bool {
return err != nil && strings.HasPrefix(err.Error(), "protocol: unknown message type")
} Try / catch
msg, err := protocol.Decode(line)
if err != nil {
if isUnknownTypeError(err) {
log.Printf("ignoring unknown message from peer: %v", err)
return nil // skip frame; keep connection alive
}
return err
} Prevention
- Always build messages with the exported MsgType* constants, never inline strings
- Pin CLI and bus process to the same release; restart the bus after upgrades
- When adding a message type, update both encoder and decoder switch in the same PR
- Log-and-skip unknown types at protocol boundaries to tolerate forward-compatible peers
When it happens
Trigger: Decode reads a line whose JSON has a 'type' value outside the known set — a peer on a newer/older protocol version, a typo'd type string, or a foreign JSON line reaching the bus stream.
Common situations: CLI and long-running bus binary updated to different versions (old bus doesn't know new message types); hand-crafted test/status probes sending wrong type; another process writing unrelated JSON into the same file/socket.
Related errors
- protocol encode: %w
- protocol decode type: %w
- Invalid column: {column!r}
- Invalid column index: {index}
- anchor outside sheet: {position!r}
AI-assisted analysis of larksuite/cli@7fd6ef3c07 (2026-09-04).
Data as JSON: /api/errors/a6316933b7b0c2c6.
Report an issue: GitHub.