{"record":{"id":"cbd5891bd68b6488","repo":"rohitg00/ai-engineering-from-scratch","slug":"bands-bands-must-divide-num-hashes-num-hashe","errorCode":null,"errorMessage":"bands ({bands}) must divide num_hashes ({num_hashes})","messagePattern":"bands \\((.+?)\\) must divide num_hashes \\((.+?)\\)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"phases/19-capstone-projects/42-large-corpus-downloader/code/main.py","lineNumber":177,"sourceCode":"                if candidate < best:\n                    best = candidate\n            sig.append(best)\n        return sig\n\n\nclass LSHIndex:\n    \"\"\"Locality-sensitive hashing index over MinHash signatures.\n\n    Splits each signature into `bands` bands of `rows = num_hashes / bands` rows.\n    Two signatures collide if they agree on at least one band. The collision\n    probability is 1 - (1 - s^r)^b where s is Jaccard similarity, which gives\n    a sharp threshold near s = (1/b)^(1/r). For (b=32, r=4) the threshold is\n    near s = 0.42; for (b=20, r=5) it is near s = 0.55.\n    \"\"\"\n\n    def __init__(self, num_hashes: int, bands: int = DEFAULT_BANDS) -> None:\n        if bands <= 0 or num_hashes % bands != 0:\n            raise ValueError(f\"bands ({bands}) must divide num_hashes ({num_hashes})\")\n        self.num_hashes = num_hashes\n        self.bands = bands\n        self.rows = num_hashes // bands\n        self._buckets: list[dict[bytes, list[str]]] = [{} for _ in range(bands)]\n        self._signatures: dict[str, list[int]] = {}\n\n    @staticmethod\n    def _band_key(band: list[int]) -> bytes:\n        return hashlib.blake2b(b\"\".join(struct.pack(\"<Q\", v) for v in band), digest_size=16).digest()\n\n    def query(self, signature: list[int]) -> str | None:\n        \"\"\"Return the doc id of a near-duplicate keeper or None.\"\"\"\n\n        for i in range(self.bands):\n            band = signature[i * self.rows : (i + 1) * self.rows]\n            key = self._band_key(band)\n            bucket = self._buckets[i].get(key)\n            if bucket:","sourceCodeStart":159,"sourceCodeEnd":195,"githubUrl":"https://github.com/rohitg00/ai-engineering-from-scratch/blob/39ea8a1c6d0b61f071226eff7ede4d4105fed820/phases/19-capstone-projects/42-large-corpus-downloader/code/main.py#L159-L195","documentation":"Error \"bands ({bands}) must divide num_hashes ({num_hashes})\" thrown in rohitg00/ai-engineering-from-scratch.","triggerScenarios":"Thrown at phases/19-capstone-projects/42-large-corpus-downloader/code/main.py:177 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":[],"exampleFix":null,"handlingStrategy":null,"validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"39ea8a1c6d0b61f071226eff7ede4d4105fed820","analyzedAt":"2026-08-26T03:13:46.626Z","schemaVersion":2},"datasetVersion":"2026-08-26T07:17:17.940Z"}