cocoindex-io/cocoindex · error · KeyError
{name}
Error message
{name} What it means
DedupMap.canonical_of() walks the dedup chain to find the canonical name for an entity. If the name was never registered in the dedup map, a KeyError(name) is raised. The map is acyclic by construction, so lookup terminates.
Source
Thrown at python/cocoindex/ops/entity_resolution/__init__.py:144
"""Result of entity resolution.
Wraps the underlying ``name -> canonical | None`` dedup map and provides
safe chain-walking. Treat as read-only; mutations are not part of the
contract.
"""
_dedup: dict[str, str | None]
def canonical_of(self, name: str) -> str:
"""Return the canonical name for ``name``.
Returns ``name`` itself if it is already canonical. Raises
:exc:`KeyError` if unknown. Terminates without cycle detection
because the dedup map is acyclic by construction (see
requirement.md § "Acyclic by construction").
"""
if name not in self._dedup:
raise KeyError(name)
current = name
while True:
target = self._dedup[current]
if target is None:
return current
current = target
def canonicals(self) -> set[str]:
"""Set of all canonical names (entries whose value is None)."""
return {name for name, target in self._dedup.items() if target is None}
def groups(self) -> dict[str, set[str]]:
"""Map each canonical name to the set of all names that resolve to
it (including itself)."""
out: dict[str, set[str]] = {c: {c} for c in self.canonicals()}
for name in self._dedup:
out[self.canonical_of(name)].add(name)
return outView on GitHub (pinned to e84aa99b32)
Solutions
- Register the name in the dedup map before calling canonical_of.
- Normalize names (strip/case-fold) before both registration and lookup.
- Wrap the call in try/except KeyError and treat the name as its own canonical form.
Example fix
// before
canonical = mapper.canonical_of(name)
// after
try:
canonical = mapper.canonical_of(name.strip().casefold())
except KeyError:
canonical = name Defensive patterns
Strategy: try-catch
Validate before calling
if name not in mapper._dedup:
canonical = name # or register it first Try / catch
try:
canonical = mapper.canonical_of(name)
except KeyError:
canonical = name # unknown names are their own canonical form Prevention
- Normalize (strip/casefold) names before registering and querying.
- Register all entity aliases before running relation/group creation.
- Decide a policy for unknown names (identity mapping vs. error).
When it happens
Trigger: Calling canonical_of(name) (directly or via create_person_relations / groups) with a name that was never added to the dedup map via the merge/record API.
Common situations: Case/whitespace mismatches between the queried name and the registered one; processing a new entity batch before registering its aliases; stale map from a previous run.
Understand the failure class
Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.
Related errors
- resolve_pair returned matched={decision.matched!r}, which is
- use_mount() requires a ComponentSubpath when the function ha
- LiveComponent classes cannot be used with use_mount(). Use m
- mount() requires a ComponentSubpath when the function has no
- mount_each() requires a ComponentSubpath when the function h
AI-assisted analysis of cocoindex-io/cocoindex@e84aa99b32 (2026-09-08).
Data as JSON: /api/errors/cbbfc9932b6ed221.
Report an issue: GitHub.