micro/go-micro · error
Failed to unmarshal object
Error message
Failed to unmarshal object
What it means
Returned by getRecord when json.Unmarshal of the value stored in the KV entry into KeyValueEnvelope fails. The plugin stores records as JSON envelopes ({key,data,metadata}), so any value in the bucket not written by this plugin (or corrupted) cannot be read.
Source
Thrown at store/nats-js-kv/nats.go:402
}
n.buckets.Set(kv.Bucket, store)
return store, nil
}
// getRecord returns the record with the given key from the nats kv store.
func (n *natsStore) getRecord(bucket nats.KeyValue, key string) (*store.Record, bool, error) {
obj, err := bucket.Get(key)
if errors.Is(err, nats.ErrKeyNotFound) {
return nil, false, store.ErrNotFound
} else if err != nil {
return nil, false, errors.Wrap(err, "Failed to get object from bucket")
}
var kv KeyValueEnvelope
if err := json.Unmarshal(obj.Value(), &kv); err != nil {
return nil, false, errors.Wrap(err, "Failed to unmarshal object")
}
if obj.Operation() != nats.KeyValuePut {
return nil, false, nil
}
return &store.Record{
Key: kv.Key,
Value: kv.Data,
Metadata: kv.Metadata,
}, true, nil
}
func (n *natsStore) natsKeys(bucket nats.KeyValue, table, key string, prefix, suffix bool) ([]string, error) {
if !suffix && !prefix {
return []string{n.NatsKey(table, key)}, nil
}
View on GitHub (pinned to 24529f1404)
Solutions
- Write all data through store.Write so entries are valid KeyValueEnvelope JSON
- If manual values exist in the bucket, re-ingress them: read raw and rewrite with store.Write (json envelope {"key":...,"data":...,"metadata":...})
- Check that the value is not empty/corrupted: 'nats kv get <bucket> <key>' and validate the JSON
- Use a separate bucket for data written by other tools instead of sharing one
Example fix
// before
nats kv put mybucket mykey --val "raw string"
st.Read("mykey") // -> Failed to unmarshal object
// after
st.Write(&store.Record{Key: "mykey", Value: []byte("raw string")})
st.Read("mykey") // ok Defensive patterns
Strategy: validation
Validate before calling
raw, err := json.Marshal(rec)
_ = raw
if json.Valid([]byte(raw)) { /* will be stored as envelope by Write */ } Type guard
func isValidEnvelope(b []byte) bool {
var kv KeyValueEnvelope
return json.Unmarshal(b, &kv) == nil
} Try / catch
_, err := st.Read(key)
if err != nil && strings.Contains(err.Error(), "Failed to unmarshal object") {
// value was written outside this plugin; re-ingest or delete it
return fmt.Errorf("bucket contains foreign data at key %s", key)
} Prevention
- Never write raw values into the bucket with 'nats kv put' or other clients; use store.Write
- Use separate buckets for data owned by other tools
- Validate stored values are JSON envelopes after any manual intervention
- Restrict bucket access to services using this store plugin
When it happens
Trigger: Calling store.Read(key) on a bucket entry that was written directly via NATS (nats kv put / another application) rather than through this store's Write, or whose envelope bytes were corrupted or truncated.
Common situations: Mixing go-micro store plugin access with manual 'nats kv put' writes of raw values; reading a bucket populated by a different tool with a different serialization format; manual edits or partial writes to the JetStream stream.
Understand the failure class
Background: "failed to unmarshal" / json.Unmarshal errors: why parsing a response into a Go struct fails and how to fix it — this error's family across 23 libraries.
Related errors
- failed to parse stream chunk: %w
- source not found: %s
- Failed to store data in bucket '%s'
- Failed to delete data
- Failed to list keys in bucket
AI-assisted analysis of micro/go-micro@24529f1404 (2026-09-01).
Data as JSON: /api/errors/107b6e2c327be7e2.
Report an issue: GitHub.