{"record":{"id":"cdc84c555477e901","repo":"cocoindex-io/cocoindex","slug":"index-key-must-be-a-db-key-index-name-tuple-go","errorCode":null,"errorMessage":"Index key must be a (db_key, index_name) tuple, got {key!r}","messagePattern":"Index key must be a \\(db_key, index_name\\) tuple, got (.+?)","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"python/cocoindex/connectors/valkey/_target.py","lineNumber":553,"sourceCode":"\n        prefix = _make_prefix(index_name)\n        options = FtCreateOptions(data_type=DataType.HASH, prefixes=[prefix])\n\n        await ft.create(client, index_name, schema=all_fields, options=options)\n\n    def reconcile(\n        self,\n        key: coco.StableKey,\n        desired_state: _IndexSpec | coco.NonExistenceType,\n        prev_possible_records: Collection[_IndexTrackingRecord],\n        prev_may_be_missing: bool,\n        /,\n    ) -> (\n        coco.TargetReconcileOutput[_IndexAction, _IndexTrackingRecord, _DocumentHandler]\n        | None\n    ):\n        if not isinstance(key, tuple) or len(key) != 2:\n            raise TypeError(\n                f\"Index key must be a (db_key, index_name) tuple, got {key!r}\"\n            )\n        key = _IndexKey(*_INDEX_KEY_CHECKER.check(key))\n        tracking_record: _IndexTrackingRecord | coco.NonExistenceType\n\n        if coco.is_non_existence(desired_state):\n            tracking_record = coco.NON_EXISTENCE\n        else:\n            tracking_record = statediff.MutualTrackingRecord(\n                tracking_record=_IndexTrackingRecordCore(\n                    vectors=desired_state.schema.vectors,\n                    fields=desired_state.schema.fields,\n                ),\n                managed_by=desired_state.managed_by,\n            )\n\n        transition = statediff.TrackingRecordTransition(\n            tracking_record,","sourceCodeStart":535,"sourceCodeEnd":571,"githubUrl":"https://github.com/cocoindex-io/cocoindex/blob/e84aa99b3292c5270a4b313b2a7137ad9ce8ab3b/python/cocoindex/connectors/valkey/_target.py#L535-L571","documentation":"This TypeError is thrown by the Valkey connector target's reconcile() when a key passed to it is not a 2-element (db_key, index_name) tuple. Target-state keys must be tuples identifying both the database and the index so the engine can match components across runs; anything else is rejected early.","triggerScenarios":"Calling reconcile (directly or via custom target plumbing) with a plain string, an int, a tuple of the wrong length, or a tuple whose elements are not valid (db_key, index_name) values.","commonSituations":"Wiring a custom or older-style target handler that passes a single connection key; refactoring from flat string keys to tuple keys; typos where a db_key string is passed instead of the pair.","solutions":["Pass a 2-tuple: (db_key, index_name) as the target-state key","Verify the tuple contents pass _INDEX_KEY_CHECKER (correct types for both elements)","Check that any wrapper code builds the key with _IndexKey(...) or the documented form"],"exampleFix":"// before\nawait target.reconcile(db_key, desired_state)\n// after\nawait target.reconcile((db_key, index_name), desired_state)","handlingStrategy":"type-guard","validationCode":"if not (isinstance(key, tuple) and len(key) == 2):\n    raise TypeError(f\"expected (db_key, index_name) tuple, got {key!r}\")","typeGuard":"def is_index_key(key: object) -> TypeGuard[tuple[object, str]]:\n    return isinstance(key, tuple) and len(key) == 2","tryCatchPattern":"try:\n    handle = await target.reconcile(key, desired)\nexcept TypeError as e:\n    if \"Index key must be\" in str(e):\n        key = (db_key, index_name)\n        handle = await target.reconcile(key, desired)\n    else:\n        raise","preventionTips":["Always construct keys via the documented (db_key, index_name) tuple","Never pass bare strings as target-state keys","Add a unit test asserting the key shape"],"tags":["python","valkey","type-error"],"backgroundTag":"invalid-argument-format","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"}