{"record":{"id":"89be281519d3207d","repo":"cocoindex-io/cocoindex","slug":"unsupported-type-for-typechecker-tp","errorCode":null,"errorMessage":"Unsupported type for TypeChecker: {tp}","messagePattern":"Unsupported type for TypeChecker: (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/cocoindex/_internal/datatype.py","lineNumber":393,"sourceCode":"            if not isinstance(value, tuple):\n                loc = f\" at {path}\" if path else \"\"\n                raise TypeError(f\"expected tuple{loc}, got {type(value).__name__}\")\n\n        return check_bare_tuple\n\n    # Simple concrete type: str, int, bytes, uuid.UUID, etc.\n    if isinstance(tp, type):\n\n        def check_isinstance(value: Any, path: str) -> None:\n            if not isinstance(value, tp):\n                loc = f\" at {path}\" if path else \"\"\n                raise TypeError(\n                    f\"expected {tp.__name__}{loc}, got {type(value).__name__}: {value!r}\"\n                )\n\n        return check_isinstance\n\n    raise ValueError(f\"Unsupported type for TypeChecker: {tp}\")\n\n\nT = TypeVar(\"T\")\n\n\nclass TypeChecker(Generic[T]):\n    \"\"\"\n    Pre-built runtime type checker.\n\n    Analyzes a type annotation once at construction time and builds optimized\n    validation closures.  At check time, validation is a fast series of\n    ``isinstance`` calls and tuple-length comparisons — no reflection.\n\n    Usage::\n\n        _TABLE_KEY_CHECKER: TypeChecker[tuple[str, str]] = TypeChecker(tuple[str, str])\n\n        # In reconcile():","sourceCodeStart":375,"sourceCodeEnd":411,"githubUrl":"https://github.com/cocoindex-io/cocoindex/blob/e84aa99b3292c5270a4b313b2a7137ad9ce8ab3b/python/cocoindex/_internal/datatype.py#L375-L411","documentation":"_build_check_fn raises this ValueError when TypeChecker is constructed with a type annotation the runtime checker builder does not know how to validate. The builder walks typing constructs (Optional, list, dict, tuple, bare classes); any annotation that falls through all branches — e.g. union of 3+ types, Literal, TypedDict, dataclass, generics like Sequence[T], callables — is rejected at TypeChecker construction time, not at check time. It is an upfront capability error: the checker cannot be built, so no value is ever validated.","triggerScenarios":"Calling TypeChecker(tp) (or _build_check_fn directly) with an unsupported annotation such as Literal['a','b'], Callable[[int], str], Sequence[int], a 3+-member union (int | str | None), TypedDict, dataclass types, or generic aliases not specially handled by the builder.","commonSituations":"Developers annotating internal function arguments or target-state keys with rich typing-library constructs and expecting TypeChecker to validate them; upgrading code that previously used simple types (str, tuple[str, str]) to fancier annotations; refactoring a shared type alias into a union or Protocol and passing it to TypeChecker.","solutions":["Replace the annotation with one of the supported forms: a plain class (str, int, bytes, uuid.UUID), Optional[X], list[X], dict[K, V], tuple[X, ...] or tuple[X, Y], or a union of at most Optional + one type.","If richer validation is needed, write a small custom isinstance-based check function instead of using TypeChecker.","Narrow the declared type at the boundary: accept the broad annotation in the signature but convert/coerce to the concrete supported type before constructing TypeChecker.","Check datatype.py for the exact supported grammar and add a branch in _build_check_fn if this is an internal type you own."],"exampleFix":"// before\n_KEY_CHECKER = TypeChecker(dict[str, str | int])  # ValueError: unsupported\n\n// after\n_KEY_CHECKER = TypeChecker(dict[str, str])  # supported concrete form","handlingStrategy":"type-guard","validationCode":"import typing\nSUPPORTED = (str, int, float, bool, bytes, type(None))\ndef _is_supported(tp) -> bool:\n    if tp in SUPPORTED or isinstance(tp, type):\n        return True\n    origin = typing.get_origin(tp)\n    if origin is typing.Union:\n        args = typing.get_args(tp)\n        return len(args) == 2 and type(None) in args\n    return origin in (list, dict, tuple, set)\n# call before construction: assert _is_supported(tp), tp","typeGuard":"def is_typechecker_supported(tp: object) -> bool:\n    \"\"\"True if _build_check_fn can handle this annotation.\"\"\"\n    import typing\n    origin = typing.get_origin(tp)\n    if origin is None:\n        return isinstance(tp, type)\n    if origin is typing.Union:\n        args = typing.get_args(tp)\n        return len(args) == 2 and type(None) in args\n    return origin in (list, dict, tuple)","tryCatchPattern":"try:\n    checker = TypeChecker(tp)\nexcept ValueError as e:\n    raise TypeError(f\"annotation {tp!r} not runtime-checkable by TypeChecker\") from e","preventionTips":["Keep TypeChecker annotations to plain classes, Optional[X], list/dict/tuple forms","Never feed Literal, Callable, Protocols, TypedDict, or 3+-way unions into TypeChecker","Test type-checker construction at import time so unsupported annotations fail in CI, not at runtime","Prefer converting rich annotations to concrete types at boundaries before validation"],"tags":["python","type-validation","internal-api"],"backgroundTag":"type-mismatch","analyzedSha":"e84aa99b3292c5270a4b313b2a7137ad9ce8ab3b","analyzedAt":"2026-09-08T15:59:19.997Z","contentChangedAt":"2026-09-08T15:59:19.997Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}