micro/go-micro · error
Failed to marshal object
Error message
Failed to marshal object
What it means
Returned by Write when json.Marshal of the KeyValueEnvelope wrapping the record fails before it is put into the bucket. The envelope contains the record key, data bytes, and metadata map, so marshal failures are rare but possible. pkg/errors wraps the underlying json error.
Source
Thrown at store/nats-js-kv/nats.go:238
opt.Database = n.opts.Database
}
if opt.Table == "" {
opt.Table = n.opts.Table
}
store, err := n.mustGetBucketByName(opt.Database)
if err != nil {
return err
}
b, err := json.Marshal(KeyValueEnvelope{
Key: rec.Key,
Data: rec.Value,
Metadata: rec.Metadata,
})
if err != nil {
return errors.Wrap(err, "Failed to marshal object")
}
if _, err := store.Put(n.NatsKey(opt.Table, rec.Key), b); err != nil {
return errors.Wrapf(err, "Failed to store data in bucket '%s'", n.NatsKey(opt.Table, rec.Key))
}
return nil
}
// Delete removes the record with the corresponding key from the store.
func (n *natsStore) Delete(key string, opts ...store.DeleteOption) error {
if err := n.initConn(); err != nil {
return err
}
opt := store.DeleteOptions{}
for _, o := range opts {View on GitHub (pinned to 24529f1404)
Solutions
- Inspect rec.Metadata for unsupported types (chan, func, complex) and remove or convert them to JSON-safe values
- Implement json.Marshaler on custom metadata value types that fail to marshal
- Marshal the record yourself in a test (json.Marshal on the same fields) to reproduce and pinpoint the offending field
- Downgrade to storing a json.RawMessage or []byte representation in Data instead of embedding raw structures in Metadata
Example fix
// before
rec := &store.Record{Key: "k", Value: data, Metadata: map[string]interface{}{"cb": make(chan int)}}
store.Write(rec)
// after
rec := &store.Record{Key: "k", Value: data, Metadata: map[string]interface{}{"id": "123"}}
store.Write(rec) Defensive patterns
Strategy: try-catch
Validate before calling
if _, err := json.Marshal(rec.Metadata); err != nil {
return fmt.Errorf("record metadata not JSON-serializable: %w", err)
} Try / catch
if err := st.Write(rec); err != nil {
if strings.Contains(err.Error(), "Failed to marshal object") {
log.Printf("dropping unserializable metadata for key %s", rec.Key)
}
return err
} Prevention
- Keep Metadata values limited to JSON-safe types (string, numbers, bool, nested maps/slices)
- Unit-test writes of representative records including their metadata
- Avoid copying arbitrary structs into Metadata; store complex values in rec.Value as bytes
- Consider json.RawMessage for pre-serialized metadata values
When it happens
Trigger: Calling store.Write(rec) where rec.Metadata contains a value that the encoding/json package cannot marshal, such as channels, funcs, complex numbers, or a struct implementing MarshalJSON that returns an error.
Common situations: Developers storing metadata maps built from arbitrary Go values (e.g. containing func or chan fields from other subsystems) into go-micro records; passing unsupported types through middleware that copies values into Metadata.
Understand the failure class
Background: json.Marshal / "failed to marshal" errors in Go: why "unsupported type" happens and how to fix it — this error's family across 22 libraries.
Related errors
- failed to marshal request: %w
- failed to marshal stream request: %w
- failed to marshal request: %w
- failed to marshal request: %w
- Invalid event returned from stroe
AI-assisted analysis of micro/go-micro@24529f1404 (2026-09-01).
Data as JSON: /api/errors/e4fd70bc8cabfe2d.
Report an issue: GitHub.