cocoindex-io/cocoindex · error · TypeError
expected tuple of length {expected_len}{loc}, got length {le
Error message
expected tuple of length {expected_len}{loc}, got length {len(value)} What it means
For fixed-length tuple types, after confirming the value is a tuple, check_fixed_tuple verifies the arity matches the number of type arguments. This TypeError is raised when a tuple of the wrong length is supplied, e.g. a 3-element tuple for tuple[int, str]. The length must match exactly because each position has its own element checker.
Source
Thrown at python/cocoindex/_internal/datatype.py:364
loc = f" at {path}" if path else ""
raise TypeError(f"expected tuple{loc}, got {type(value).__name__}")
for i, elem in enumerate(value):
elem_fn(elem, f"{path}[{i}]")
return check_var_tuple
if args:
# Fixed-length: tuple[X, Y, ...]
elem_fns = [_build_check_fn(a) for a in args]
expected_len = len(args)
def check_fixed_tuple(value: Any, path: str) -> None:
if not isinstance(value, tuple):
loc = f" at {path}" if path else ""
raise TypeError(f"expected {tp}{loc}, got {type(value).__name__}")
if len(value) != expected_len:
loc = f" at {path}" if path else ""
raise TypeError(
f"expected tuple of length {expected_len}{loc}, "
f"got length {len(value)}"
)
for i, (elem, fn) in enumerate(zip(value, elem_fns)):
fn(elem, f"{path}[{i}]")
return check_fixed_tuple
# Bare tuple (no args) — just check isinstance
def check_bare_tuple(value: Any, path: str) -> None:
if not isinstance(value, tuple):
loc = f" at {path}" if path else ""
raise TypeError(f"expected tuple{loc}, got {type(value).__name__}")
return check_bare_tuple
# Simple concrete type: str, int, bytes, uuid.UUID, etc.
if isinstance(tp, type):View on GitHub (pinned to e84aa99b32)
Solutions
- Fix the producer so it emits exactly the declared number of elements
- If arity is genuinely variable, switch the declared type to a dataclass, NamedTuple, or tuple[X, ...] as appropriate
- Log/print the value before the call to see which element count is being produced
Example fix
// before return (user_id, name, email) # declared tuple[int, str] // after return (user_id, name)
Defensive patterns
Strategy: validation
Validate before calling
if not (isinstance(value, tuple) and len(value) == expected_len):
raise ValueError(f"need tuple of length {expected_len}, got {value!r}") Type guard
def has_arity(value: object, n: int) -> TypeGuard[tuple]:
return isinstance(value, tuple) and len(value) == n Try / catch
try:
check(value)
except TypeError as e:
if "expected tuple of length" in str(e):
log.error("arity mismatch: %s", e)
raise Prevention
- Keep producers and declared tuple types in sync — update both when fields change
- Build fixed-arity values via a small factory function that asserts length once
- Add a unit test that checks representative values against the declared type
When it happens
Trigger: Passing a tuple whose len() differs from the declared arity — e.g. (1, 'a', True) where tuple[int, str] is declared, or an empty tuple () for any non-empty fixed tuple type, via a @coco.fn argument, target-state field, or TypeChecker.check().
Common situations: Appending/removing a field from the declared type without updating producers; spreading optional values conditionally; building the tuple dynamically with variable item counts.
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
- expected {tp}{loc}, got {type(value).__name__}
- expected tuple{loc}, got {type(value).__name__}
- expected {tp.__name__}{loc}, got {type(value).__name__}: {va
- use_mount() requires a ComponentSubpath when the function ha
- LiveComponent classes cannot be used with use_mount(). Use m
AI-assisted analysis of cocoindex-io/cocoindex@e84aa99b32 (2026-09-08).
Data as JSON: /api/errors/796b920578433775.
Report an issue: GitHub.