{"record":{"id":"0a9ed40a141e7243","repo":"cocoindex-io/cocoindex","slug":"context-key-key-expected-t-name-got-t","errorCode":null,"errorMessage":"Context key '{key}': expected {t.__name__}, got {type(value).__name__}","messagePattern":"Context key '(.+?)': expected (.+?), got (.+?)","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"python/cocoindex/_internal/context_keys.py","lineNumber":265,"sourceCode":"\n    @overload\n    def get(self, key: ContextKey[T]) -> T: ...\n    @overload\n    def get(self, key: str) -> Any: ...\n    @overload\n    def get(self, key: str, t: type[T]) -> T: ...\n    def get(self, key: ContextKey[T] | str, t: type[T] | None = None) -> Any:\n        \"\"\"Get a value from the context. Raises KeyError if not found.\n\n        Overloads:\n          get(key: ContextKey[T]) -> T\n          get(key: str) -> Any\n          get(key: str, t: type[T]) -> T  — also verifies the type at runtime\n        \"\"\"\n        if isinstance(key, str):\n            value = self._values[key]\n            if t is not None and not isinstance(value, t):\n                raise TypeError(\n                    f\"Context key '{key}': expected {t.__name__}, got {type(value).__name__}\"\n                )\n            return value\n        return cast(T, self._values[key._key])\n\n    async def aclose(self) -> None:\n        await self._exit_stack.aclose()\n","sourceCodeStart":247,"sourceCodeEnd":273,"githubUrl":"https://github.com/cocoindex-io/cocoindex/blob/e84aa99b3292c5270a4b313b2a7137ad9ce8ab3b/python/cocoindex/_internal/context_keys.py#L247-L273","documentation":"ContextProvider.get accepts an optional type parameter `t`; when given a string key plus a type, it verifies the retrieved value is an instance of that type at runtime and raises TypeError on mismatch. This catches provider/consumer type disagreements early.","triggerScenarios":"Calling provider.get(\"some_key\", MyType) (string form) where the value stored under that key was provided with a different Python type — e.g. provided an asyncpg.Pool but requested str, or provided a Path but requested str.","commonSituations":"Key string collides across providers storing different types; refactoring changed the provided type but not the consumer's declared type; passing a subclass-expected type where value is a duck-typed lookalike (isinstance check fails).","solutions":["Make the requested type match what was actually provided, or cast/coerce the value after retrieval","Retrieve via the typed ContextKey[T] object instead of the string+type form so types are checked at the provider boundary","Fix the provide() call site to store the correct type"],"exampleFix":"// before\npool = ctx.get(\"db\", str)  # stored value is a Pool\n\n// after\npool = ctx.get(DB_KEY)  # typed ContextKey[asyncpg.Pool]","handlingStrategy":"type-guard","validationCode":"if not isinstance(ctx._values.get(\"db_key\"), MyType):\n    raise TypeError(\"context value has wrong type before get()\")","typeGuard":"def is_pool(v: object) -> TypeGuard[asyncpg.Pool]:\n    return isinstance(v, asyncpg.Pool)","tryCatchPattern":"try:\n    pool = ctx.get(\"db\", asyncpg.Pool)\nexcept TypeError as e:\n    logging.error(\"context type mismatch: %s\", e)\n    pool = build_pool_fallback()","preventionTips":["Prefer typed ContextKey[T] lookups over raw string keys","Keep provide() and get() types in the same module so they can't drift","Run mypy across provide/get call sites"],"tags":["python","typing","type-mismatch","context"],"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"}