cayleygraph/cayley · error

unexpected type for pb field: %T

Error message

unexpected type for pb field: %T

What it means

toQuadValue decodes protobuf-encoded pquads.Value blobs from the document; this error is thrown when the pb field is neither a nosql.String (base64) nor nosql.Bytes. It means the stored value field has an unexpected type for the protobuf value encoding path.

Source

Thrown at graph/nosql/quadstore.go:537

	}
	return vi, nil
}

func toQuadValue(opt *Traits, d nosql.Document) (quad.Value, error) {
	if len(d) == 0 {
		return nil, nil
	}
	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)

View on GitHub (pinned to 81dcd7d73e)

Solutions

  1. Inspect %T of the value to identify the actual stored type and its origin.
  2. Re-load the affected data through the current Cayley version so values are encoded as pquads protobuf blobs.
  3. If you control the writer, store values as nosql.Bytes (or base64 nosql.String) after proto.Marshal of pquads.Value.
  4. Exclude/repair corrupt documents — dump and re-import the store to rebuild value documents.
  5. Verify you are reading the intended field (fldValPB) rather than another value-kind field.

Example fix

// before
default:
    err = fmt.Errorf("unexpected type for pb field: %T", v)
// after
case nosql.String: // existing base64 path
    b, err = base64.StdEncoding.DecodeString(string(v))
case nosql.Bytes:
    b = []byte(v)
default:
    return nil, fmt.Errorf("unexpected type for pb field: %T", v)
Defensive patterns

Strategy: type-guard

Validate before calling

func isPBValue(v nosql.Value) bool {
    switch v.(type) {
    case nosql.String, nosql.Bytes:
        return true
    }
    return false
}

Type guard

func pbBytes(v interface{}) ([]byte, bool) {
    switch t := v.(type) {
    case nosql.String:
        b, err := base64.StdEncoding.DecodeString(string(t))
        return b, err == nil
    case nosql.Bytes:
        return []byte(t), true
    }
    return nil, false
}

Try / catch

val, err := toQuadValue(opt, doc)
if err != nil {
    log.Printf("unreadable value doc (re-import needed): %v", err)
    return quad.Raw(""), nil // or skip the document
}

Prevention

When it happens

Trigger: NameOf/toQuadValue reading a document whose fldValPB field holds a different nosql type (Int, Bool, Time) — data written by an incompatible writer/encoder or a mis-mapped field.

Common situations: Quadstore data written before the pquads protobuf value encoding or by a different storage layout; a corrupted document from a crashed bulk load; custom import tools storing raw strings without base64/proto encoding.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


AI-assisted analysis of cayleygraph/cayley@81dcd7d73e (2026-09-06). Data as JSON: /api/errors/d2193412e7bbfabe. Report an issue: GitHub.