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

  1. Inspect rec.Metadata for unsupported types (chan, func, complex) and remove or convert them to JSON-safe values
  2. Implement json.Marshaler on custom metadata value types that fail to marshal
  3. Marshal the record yourself in a test (json.Marshal on the same fields) to reproduce and pinpoint the offending field
  4. 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

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


AI-assisted analysis of micro/go-micro@24529f1404 (2026-09-01). Data as JSON: /api/errors/e4fd70bc8cabfe2d. Report an issue: GitHub.