canopy-network/canopy · error · ErrJSONUnmarshal
ErrJSONUnmarshal
ErrJSONUnmarshal
Error message
empty json payload
What it means
Raised in AnyFromProtoJSON (lib/codec.go:63) when the input json.RawMessage is empty (len 0). There is no JSON to unmarshal into a protobuf.Any, so the conversion is rejected up front with ErrJSONUnmarshal instead of producing a nil/degenerate Any.
Source
Thrown at lib/codec.go:63
return nil, fmt.Errorf("unable to marshal any payload type %s to json", any.TypeUrl)
}
// MarshalAnyProtoJSON() converts an 'any proto' into JSON
func MarshalAnyProtoJSON(any *anypb.Any) (json.RawMessage, error) {
if any == nil {
return nil, nil
}
jsonBytes, err := protojson.MarshalOptions{}.Marshal(any)
if err != nil {
return nil, ErrJSONMarshal(err)
}
return jsonBytes, nil
}
// AnyFromProtoJSON() converts JSON into a protobuf.Any
func AnyFromProtoJSON(msg json.RawMessage) (a *anypb.Any, e ErrorI) {
if len(msg) == 0 {
return nil, ErrJSONUnmarshal(fmt.Errorf("empty json payload"))
}
a = new(anypb.Any)
if err := protojson.Unmarshal(msg, a); err != nil {
return nil, ErrJSONUnmarshal(err)
}
return a, nil
}
// AnyFromJSONForMessageType() converts JSON into anypb
func AnyFromJSONForMessageType(messageType string, msg json.RawMessage) (*anypb.Any, ErrorI) {
if messageType == "" {
return nil, ErrUnknownMessageName(messageType)
}
desc := globalPluginSchemaRegistry.FindMessageDescriptorForMessageType(messageType)
typeURL := messageType
if strings.Contains(messageType, "/") {
desc = globalPluginSchemaRegistry.FindMessageDescriptorForTypeURL(messageType)
} else if desc != nil {View on GitHub (pinned to ee8197d91d)
Solutions
- Ensure the JSON being unmarshaled contains a non-empty payload (check len before calling)
- Fix the producer so it omits the call entirely or emits at least '{}' instead of empty bytes
- Guard the caller: skip AnyFromProtoJSON when json.RawMessage is nil/empty
Example fix
// before
var msg json.RawMessage
a, err := lib.AnyFromProtoJSON(msg) // msg is empty
// after
if len(msg) == 0 {
return fmt.Errorf("missing parameter payload")
}
a, err := lib.AnyFromProtoJSON(msg) Defensive patterns
Strategy: validation
Validate before calling
if len(raw) == 0 {
return errors.New("refusing to unmarshal empty json payload")
} Type guard
func nonEmptyJSON(m json.RawMessage) bool { return len(m) > 0 } Try / catch
a, err := lib.AnyFromProtoJSON(raw)
var eErr *fsm.ErrorI
if err != nil && strings.Contains(err.Error(), "empty json payload") {
// treat as missing parameter field
} Prevention
- Omit the call rather than passing empty bytes
- Emit '{}' or a real payload instead of empty raw JSON from producers
- Validate tx JSON completeness before signing/submission
When it happens
Trigger: AnyFromProtoJSON is called from UnmarshalJSON with an empty (zero-length) json.RawMessage — e.g. the message's parameterValue/parameter bytes were empty or the field was omitted so nothing was passed through.
Common situations: A client submits a tx JSON with a missing/empty parameter field; upstream marshaling produced empty raw JSON; a nil value was serialized as an empty slice.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- unknown parameter type %T
- unable to marshal any payload type %s to json
- Item too long: {len(item)} bytes (max 255)
- Invalid uint64 value: {value}
- Invalid chain_id: {self.chain_id}
AI-assisted analysis of canopy-network/canopy@ee8197d91d (2026-09-06).
Data as JSON: /api/errors/9eb3730bb62faf44.
Report an issue: GitHub.