{"record":{"id":"79116f595a16e210","repo":"headroomlabs-ai/headroom","slug":"memory-ids-len-memory-ids-and-texts-len-tex","errorCode":null,"errorMessage":"memory_ids ({len(memory_ids)}) and texts ({len(texts)}) must have same length","messagePattern":"memory_ids \\((.+?)\\) and texts \\((.+?)\\) must have same length","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"headroom/memory/adapters/fts5.py","lineNumber":162,"sourceCode":"\n    def index_batch(\n        self,\n        memory_ids: list[str],\n        texts: list[str],\n        metadata: list[dict] | None = None,\n    ) -> None:\n        \"\"\"Index multiple memories in a single transaction.\n\n        Args:\n            memory_ids: List of unique identifiers.\n            texts: List of text contents to index.\n            metadata: Optional list of metadata dicts (one per memory).\n\n        Raises:\n            ValueError: If memory_ids and texts have different lengths.\n        \"\"\"\n        if len(memory_ids) != len(texts):\n            raise ValueError(\n                f\"memory_ids ({len(memory_ids)}) and texts ({len(texts)}) must have same length\"\n            )\n\n        if metadata is not None and len(metadata) != len(memory_ids):\n            raise ValueError(\n                f\"metadata ({len(metadata)}) must match memory_ids ({len(memory_ids)}) length\"\n            )\n\n        metadata = metadata or [{} for _ in memory_ids]\n\n        with self._get_conn() as conn:\n            # Delete existing entries\n            conn.executemany(\n                \"DELETE FROM memory_fts WHERE memory_id = ?\",\n                [(mid,) for mid in memory_ids],\n            )\n\n            # Prepare batch data","sourceCodeStart":144,"sourceCodeEnd":180,"githubUrl":"https://github.com/headroomlabs-ai/headroom/blob/322425c43bffde1ed0b64fecf3cf5951565dd82b/headroom/memory/adapters/fts5.py#L144-L180","documentation":"FTS5TextIndex.index_batch validates that its parallel list arguments have identical lengths before touching SQLite; memory_ids and texts must pair one-to-one. This ValueError fails fast so the executemany DELETE/INSERT inside a single transaction never processes misaligned rows.","triggerScenarios":"Calling index_batch(memory_ids, texts) where the lists differ in length — e.g. ids generated per unique memory but texts per chunk, zipping that dropped elements, or a filtered list applied to only one of the two arguments.","commonSituations":"Chunking/dedup pipelines that shrink one list and not the other; batch code that appends ids for successful extractions but texts for all inputs; upstream scanner returning ragged batches; off-by-one slicing.","solutions":["Inspect the two counts in the message to find where the divergence starts.","Build pairs and derive both lists from one structure: [(mid, text), ...] so they cannot drift.","If chunking, repeat the memory_id per chunk instead of producing separate-length lists.","Add an assert len(ids) == len(texts) in your producer code near the source of the mismatch."],"exampleFix":"# before\nindex.index_batch(ids, chunked_texts)  # 10 ids, 23 chunks -> ValueError\n\n# after\npairs = [(mid, chunk) for mid, chunks in zip(ids, chunked) for chunk in chunks]\nindex.index_batch([p[0] for p in pairs], [p[1] for p in pairs])","handlingStrategy":"validation","validationCode":"def valid_batch(ids: list[str], texts: list[str], metadata: list | None) -> bool:\n    \"\"\"True when index_batch's parallel-array invariants hold.\"\"\"\n    if len(ids) != len(texts):\n        return False\n    return metadata is None or len(metadata) == len(ids)","typeGuard":null,"tryCatchPattern":"try:\n    index.index_batch(ids, texts)\nexcept ValueError as e:\n    if \"must have same length\" in str(e):\n        raise SystemExit(f\"producer bug: ragged batch ({e}); fix upstream list construction\") from e\n    raise","preventionTips":["Build (id, text) pairs first and unzip, so the lists cannot diverge.","Add len() assertions in the batch producer right where filtering happens.","Cover the batch producer with a unit test asserting equal lengths."],"tags":["validation","batch","fts5","memory","invariant"],"backgroundTag":null,"analyzedSha":"322425c43bffde1ed0b64fecf3cf5951565dd82b","analyzedAt":"2026-08-15T01:03:05.481Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}