{"record":{"id":"14ae7646622e14a2","repo":"langchain-ai/langchain","slug":"batch-size-must-be-a-positive-integer-got-size","errorCode":null,"errorMessage":"Batch size must be a positive integer, got {size}.","messagePattern":"Batch size must be a positive integer, got (.+?)\\.","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"libs/core/langchain_core/indexing/api.py","lineNumber":95,"sourceCode":"    if algorithm == \"sha1\":\n        _warn_about_sha1()\n    hash_value = _calculate_hash(input_string, algorithm)\n    return uuid.uuid5(NAMESPACE_UUID, hash_value)\n\n\ndef _hash_nested_dict(\n    data: dict[Any, Any], *, algorithm: Literal[\"sha1\", \"sha256\", \"sha512\", \"blake2b\"]\n) -> uuid.UUID:\n    \"\"\"Hash a nested dictionary to a UUID using the configured algorithm.\"\"\"\n    serialized_data = json.dumps(data, sort_keys=True)\n    return _hash_string(serialized_data, algorithm=algorithm)\n\n\ndef _batch(size: int, iterable: Iterable[T]) -> Iterator[list[T]]:\n    \"\"\"Utility batching function.\"\"\"\n    if size <= 0:\n        msg = f\"Batch size must be a positive integer, got {size}.\"\n        raise ValueError(msg)\n    it = iter(iterable)\n    while True:\n        chunk = list(islice(it, size))\n        if not chunk:\n            return\n        yield chunk\n\n\nasync def _abatch(size: int, iterable: AsyncIterable[T]) -> AsyncIterator[list[T]]:\n    \"\"\"Utility batching function.\"\"\"\n    if size <= 0:\n        msg = f\"Batch size must be a positive integer, got {size}.\"\n        raise ValueError(msg)\n    batch: list[T] = []\n    async for element in iterable:\n        if len(batch) < size:\n            batch.append(element)\n","sourceCodeStart":77,"sourceCodeEnd":113,"githubUrl":"https://github.com/langchain-ai/langchain/blob/e32fa9a52eab3b61ad7a45399bfde59b3e580fc4/libs/core/langchain_core/indexing/api.py#L77-L113","documentation":"Raised by the internal `_batch()` helper in `langchain_core.indexing.api`. `aindex`/indexing pipelines split the document stream into fixed-size chunks for batched writes; a chunk size of zero or a negative number would produce empty or infinite batches, so it is rejected upfront with a `ValueError`. The message interpolates the offending size.","triggerScenarios":"Calling `index()`/`aindex()` with `batch_size=0` or a negative number, or with a value computed at runtime (e.g. `max(1, n // workers)` where n is 0 yields... actually that clamps; more typically `n // workers` with small n yields 0). Also direct use of `_batch` in custom code.","commonSituations":"Deriving batch_size from a config/env var that defaults to 0; dividing document count by a large concurrency factor; passing `batch_size=None` through untyped code that coerces to 0.","solutions":["Set an explicit positive batch_size, e.g. `index(vs, docs, record_manager, batch_size=100)`.","Clamp computed values: `batch_size = max(1, computed)`.","Validate configuration at startup so the failure surfaces before indexing begins."],"exampleFix":"# before\nindex(vs, docs, rm, batch_size=len(docs) // num_workers)  # 0 when len(docs) < workers\n\n# after\nindex(vs, docs, rm, batch_size=max(1, len(docs) // num_workers))","handlingStrategy":"validation","validationCode":"batch_size = batch_size if isinstance(batch_size, int) and batch_size > 0 else 100\nindex(vs, docs, rm, batch_size=batch_size, cleanup=\"full\")","typeGuard":"def is_valid_batch_size(n) -> bool:\n    return isinstance(n, int) and not isinstance(n, bool) and n > 0","tryCatchPattern":null,"preventionTips":["Clamp computed batch sizes with max(1, value).","Validate batch_size in config loading so bad values fail before a long indexing run."],"tags":["indexing","batching","validation"],"backgroundTag":null,"analyzedSha":"e32fa9a52eab3b61ad7a45399bfde59b3e580fc4","analyzedAt":"2026-08-14T18:42:09.092Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}