Skip to content

hit["_id"] raises bare KeyError('_id') even though _id is the wire field name #692

Description

@joerg84

Repro

res = index.search(namespace="ns", query={...})
hit = res.result.hits[0]
hit["_id"]
# KeyError: '_id'

Root cause

Hit is a msgspec Struct with rename={"id_": "_id", "score_": "_score"} — the wire format genuinely calls these fields _id/_score, and that's what raw-REST examples and response JSON show. Hit.__getitem__ supports "id", "score", and the struct fields, and raises KeyError(key) for everything else — so exactly the two names the API itself uses are the ones that fail, with no hint.

Proposed fix

Teach in the error. When the key is a known wire alias, say what to use:

KeyError: '_id' is the wire name for this field; on Hit use hit["id"] / hit.id (likewise '_score' → hit["score"] / hit.score)

and for other unknown keys, list what exists: available keys: 'id', 'score', 'fields' (record fields live in hit["fields"]).

Alternative worth considering: simply accept "_id"/"_score" as read aliases in __getitem__/__contains__, so code written against the wire JSON ports directly. Happy to go either way — the teaching KeyError is the smaller change and steers callers to the canonical names.

How we found it

Cold-agent audit for an upcoming blog post: 2 of 2 SDK-path agents wrote hit["_id"] (copying the shape they'd just upserted), hit the bare KeyError, and had to introspect/read models/vectors/search.py to discover .id/.score.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions