larksuite/cli · error

protocol decode %s: %w

Error message

protocol decode %s: %w

What it means

Decode in internal/event/adapter/localbus/protocol/codec.go wraps a json.Unmarshal failure that occurs while decoding the payload of a recognized localbus envelope message type. The envelope was parsed and its type was known (e.g. SourceStatus), but the JSON body did not match the expected struct. The wrapper preserves the envelope type and the underlying JSON error cause.

Source

Thrown at internal/event/adapter/localbus/protocol/codec.go:120

		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

  1. Log the wrapped cause (%w) to see the exact field/type mismatch, then inspect the raw line for the offending field
  2. Verify all bus producers and consumers use the same protocol version / generated structs
  3. Re-encode the frame with this library's Encode so it matches the canonical struct shape
  4. Add a regression test (see TestEncodeDecode*) round-tripping the message to catch drift

Example fix

// before
msg, err := protocol.Decode(line)
if err != nil { return err } // opaque
// after
msg, err := protocol.Decode(line)
if err != nil {
    return fmt.Errorf("decode localbus frame: %w", err) // cause names the bad field
}
Defensive patterns

Strategy: try-catch

Validate before calling

if !json.Valid(frame) { return fmt.Errorf("frame is not valid JSON") }

Type guard

func isDecodeError(err error) bool { return err != nil && strings.Contains(err.Error(), "protocol decode ") }

Try / catch

msg, err := protocol.Decode(line)
if err != nil {
    var jsonErr *json.UnmarshalTypeError
    if errors.As(err, &jsonErr) {
        log.Printf("bad field %s in frame type", jsonErr.Field)
    }
    return fmt.Errorf("skip malformed frame: %w", err)
}

Prevention

When it happens

Trigger: Decode() receives a line whose envelope type maps to a concrete struct (e.g. &SourceStatus{}) but json.Unmarshal(line, msg) fails because the body has fields with wrong types (string where number expected), malformed JSON, or null where a struct is required.

Common situations: A producer on the bus was built with a different protocol version and serializes fields with changed types; a corrupted or truncated frame on the local transport; a test or custom peer hand-writes frames that do not match the canonical struct encoding.

Related errors


AI-assisted analysis of larksuite/cli@7fd6ef3c07 (2026-09-04). Data as JSON: /api/errors/6f296a0fe0bdf31c. Report an issue: GitHub.