cayleygraph/cayley · error
couldn't decode value: %v
Error message
couldn't decode value: %v
What it means
After successfully obtaining the raw bytes of a protobuf value, toQuadValue runs proto.Unmarshal into pquads.Value; this error wraps any unmarshal failure. The bytes exist but are not a valid pquads.Value message — the stored blob is malformed, truncated, or encoded by an incompatible proto schema.
Source
Thrown at graph/nosql/quadstore.go:544
}
var err error
// prefer protobuf representation
if v, ok := d[fldValPb]; ok {
var b []byte
switch v := v.(type) {
case nosql.String:
b, err = base64.StdEncoding.DecodeString(string(v))
case nosql.Bytes:
b = []byte(v)
default:
err = fmt.Errorf("unexpected type for pb field: %T", v)
}
if err != nil {
return nil, err
}
var p pquads.Value
if err := proto.Unmarshal(b, &p); err != nil {
return nil, fmt.Errorf("couldn't decode value: %v", err)
}
return p.ToNative(), nil
} else if v, ok := d[fldValInt]; ok {
if opt.Number32 {
// parse from string, so we are confident that we will get exactly the same value
if vs, ok := d[fldValStrInt].(nosql.String); ok {
iv := quad.Int(stoi(string(vs)))
return iv, nil
}
}
vi, err := asInt(v)
if err != nil {
return nil, err
}
return quad.Int(vi), nil
} else if v, ok := d[fldValFloat]; ok {
var vf quad.Float
switch v := v.(type) {View on GitHub (pinned to 81dcd7d73e)
Solutions
- Identify the affected documents and delete/rewrite their value fields with a fresh proto.Marshal(pquads.Value).
- Dump and re-import the store to regenerate all protobuf value blobs.
- Confirm the pquads proto schema version matches the Cayley version reading the data.
- If the error is transient storage corruption, restore from backup or re-run the import that wrote the values.
Example fix
// before
if err := proto.Unmarshal(b, &p); err != nil {
return nil, fmt.Errorf("couldn't decode value: %v", err)
}
// after
// writer side: ensure valid encoding
raw, err := proto.Marshal(&pquads.Value{...})
if err != nil { return err }
doc[fldValPB] = nosql.Bytes(raw) Defensive patterns
Strategy: try-catch
Validate before calling
// sanity check blob non-empty before unmarshal
if len(b) == 0 {
return nil, errors.New("empty pb value blob")
} Try / catch
val, err := toQuadValue(opt, doc)
if err != nil && strings.HasPrefix(err.Error(), "couldn't decode value") {
log.Printf("corrupt protobuf value, dropping doc: %v", err)
return quad.Raw(""), nil
} Prevention
- Don't interrupt bulk imports mid-write; resume rather than kill
- Keep the pquads proto schema version consistent with reader
- Back up the store before migrations
- Re-import corrupted value blobs via proto.Marshal of a fresh pquads.Value
When it happens
Trigger: Reading a fldValPB field whose bytes were corrupted (partial write), hand-edited, or written with a different protobuf schema/version so Unmarshal fails.
Common situations: Interrupted bulk import leaving truncated value blobs; schema drift between Cayley versions of pquads.Value; custom tooling writing wrong bytes into the pb field.
Understand the failure class
Background: "cannot parse invalid wire-format data", "cannot unmarshal", "failed unmarshalling": protobuf unmarshal errors explained — this error's family across 10 libraries.
Related errors
- unexpected type for int field: %T
- unexpected type for pb field: %T
- unmarshal value: %w
- unexpected int size: %d
- error updating node: %v
AI-assisted analysis of cayleygraph/cayley@81dcd7d73e (2026-09-06).
Data as JSON: /api/errors/3351c3dc75457ea3.
Report an issue: GitHub.