{"record":{"id":"e981980f6fe1e5c8","repo":"cocoindex-io/cocoindex","slug":"context-key-key-already-used","errorCode":null,"errorMessage":"Context key {key} already used","messagePattern":"Context key (.+?) already used","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/cocoindex/_internal/context_keys.py","lineNumber":107,"sourceCode":"        running_loop_error_msg=(\n            f\"Async state function on detect_change context key {key_name!r} \"\n            \"cannot be called from a running event loop at provide() time. \"\n            \"Use a sync state function, or provide the value outside of an \"\n            \"async context.\"\n        ),\n    )\n    return [outcome.state for outcome in outcomes]\n\n\nclass ContextKey(Generic[T_co]):\n    __slots__ = (\"_key\", \"_detect_change\")\n    _key: str\n    _detect_change: bool\n\n    def __init__(self, key: str, *, detect_change: bool = False):\n        with _lock:\n            if key in _used_keys:\n                raise ValueError(f\"Context key {key} already used\")\n            _used_keys.add(key)\n        self._key = key\n        self._detect_change = detect_change\n\n    @property\n    def detect_change(self) -> bool:\n        return self._detect_change\n\n    @property\n    def key(self) -> str:\n        return self._key\n\n    def __coco_memo_key__(self) -> str:\n        return self._key\n\n\nclass ContextProvider:\n    __slots__ = (","sourceCodeStart":89,"sourceCodeEnd":125,"githubUrl":"https://github.com/cocoindex-io/cocoindex/blob/e84aa99b3292c5270a4b313b2a7137ad9ce8ab3b/python/cocoindex/_internal/context_keys.py#L89-L125","documentation":"ContextKey names are globally unique in a process. The constructor registers each key string in a process-wide set guarded by a lock; constructing a second ContextKey with the same string raises ValueError so that two independently-created keys can never alias the same context slot.","triggerScenarios":"Calling ContextKey(\"db_pool\") (or any subclass/factory) twice at module level or in a function that runs multiple times — e.g. a module imported twice with different paths, a factory function invoked per-request, a test re-running module setup in the same process, or module reload.","commonSituations":"Defining the same key string in two modules; creating keys dynamically inside a loop or fixture; hot-reloading a module during development.","solutions":["Define each ContextKey once at module scope and import it wherever needed","Use a distinct, namespaced string for each key (e.g. \"myapp.pg_pool\")","In tests, create the key in a fresh subprocess or pick a unique suffix per test run"],"exampleFix":"// before\nkey = ContextKey(\"db\")   # second definition, same string\n\n// after\nfrom myapp.context_keys import DB_KEY  # single module-level definition","handlingStrategy":"validation","validationCode":"_seen_keys: set[str] = set()\ndef make_key(name: str) -> str:\n    if name in _seen_keys:\n        raise AssertionError(f\"duplicate ContextKey {name}\")\n    _seen_keys.add(name)\n    return name","typeGuard":null,"tryCatchPattern":"try:\n    key = ContextKey(\"db_pool\")\nexcept ValueError as e:\n    key = EXISTING_DB_KEY  # reuse the module-level key\n    logging.warning(\"ContextKey reused: %s\", e)","preventionTips":["Define all ContextKey instances once at module import time","Namespace key strings (e.g. \"myapp.db_pool\")","Avoid creating keys inside functions, loops, or per-test fixtures"],"tags":["python","context","duplicate-key"],"backgroundTag":"conflicting-config-options","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"}