hashicorp/nomad · error
failed to decode data into passed object: %v
Error message
failed to decode data into passed object: %v
What it means
boltdd.Bucket.Get wraps a failure of the msgpack decoder when unmarshaling the stored bytes into the caller-supplied obj pointer. The key existed (otherwise a NotFound error is returned) but its stored representation cannot be decoded into the target type. Typically the stored schema and the Go struct have drifted.
Source
Thrown at helper/boltdd/boltdd.go:353
// New value written, store hash (bucket path map was created above)
b.bm.setHash(hashKey, hashVal[:])
return nil
}
// Get value by key from boltdb or return an ErrNotFound error if key not
// found.
func (b *Bucket) Get(key []byte, obj interface{}) error {
// Get the raw data from the underlying boltdb
data := b.boltBucket.Get(key)
if data == nil {
return NotFound(string(key))
}
// Deserialize the object
if err := codec.NewDecoderBytes(data, structs.MsgpackHandle).Decode(obj); err != nil {
return fmt.Errorf("failed to decode data into passed object: %v", err)
}
return nil
}
// Iterate iterates each key in Bucket b that starts with prefix. fn is called on
// the key and msg-pack decoded value. If prefix is empty or nil, all keys in the
// bucket are iterated.
//
// b must already exist.
func Iterate[T any](b *Bucket, prefix []byte, fn func([]byte, T)) error {
c := b.boltBucket.Cursor()
for k, data := c.Seek(prefix); k != nil && bytes.HasPrefix(k, prefix); k, data = c.Next() {
var obj T
if err := codec.NewDecoderBytes(data, structs.MsgpackHandle).Decode(&obj); err != nil {
return fmt.Errorf("failed to decode data into passed object: %v", err)
}
fn(k, obj)View on GitHub (pinned to 482b49bf1a)
Solutions
- Check the wrapped %v decode error for the offending field index/type mismatch.
- Verify obj is a non-nil pointer to a type matching the struct originally written with Put.
- If the schema changed, migrate old records (decode with the old struct version, re-encode with the new one) or keep msgpack field order/types stable.
- Use a versioned payload struct (wrap data in {Version, Body}) so future changes can be handled explicitly.
Example fix
// before
var meta NodeMeta
bucket.Get(key, &meta) // stored layout has field 3 as int64, meta has time.Duration
// after
var meta nodeMetaV1 // legacy struct matching on-disk layout
if err := bucket.Get(key, &meta); err == nil {
meta2 := upgrade(meta) // migrate to current struct
} Defensive patterns
Strategy: try-catch
Validate before calling
// ensure obj is a non-nil pointer of the expected type before calling Get
rv := reflect.ValueOf(obj)
if rv.Kind() != reflect.Ptr || rv.IsNil() {
return errors.New("Get requires a non-nil pointer")
} Type guard
func isReadableInto(obj interface{}) bool {
if obj == nil { return false }
rv := reflect.ValueOf(obj)
return rv.Kind() == reflect.Ptr && !rv.IsNil() && rv.Elem().CanSet()
} Try / catch
var meta NodeMeta
if err := bucket.Get(key, &meta); err != nil {
if IsNotFound(err) {
// key absent: create default
} else if strings.Contains(err.Error(), "failed to decode") {
// schema drift: log stored bytes hash, run migration path
}
return err
} Prevention
- Never change the Go type of an existing persisted field; add new fields only (append-only schema).
- Wrap persisted payloads in a versioned envelope so old records can be decoded by old structs.
- Round-trip test persisted structs (Put then Get) in CI.
- Always pass a non-nil pointer of the same struct type used at Put time.
When it happens
Trigger: Calling Get(key, &obj) where the bytes at key were written by an older version with a different struct layout (renamed/retyped fields, changed msgpack field ordering); the stored bytes were written with a different codec/handle; obj is not a pointer or is an incompatible type for the encoded shape.
Common situations: Consul/serf state files written by an older binary read after an upgrade; changing a field's Go type (e.g. string to time.Duration) in a persisted struct; reusing a bucket key for a different type; passing a non-pointer or wrong-typed obj to Get.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- failed to decode task state from 'simple-all' entry: %v
- failed to encode passed object: %v
- failed to msgpack encode config: %v
- bad length: %d
- failed to decode log entry at index %d: %v
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/394c3ee2e32c0ecd.
Report an issue: GitHub.