{"record":{"id":"cc16a1f23272ea44","repo":"apache/beam","slug":"batch-size-must-be-a-positive-integer","errorCode":null,"errorMessage":"Batch size must be a positive integer","messagePattern":"Batch size must be a positive integer","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"sdks/python/apache_beam/ml/rag/ingestion/qdrant.py","lineNumber":201,"sourceCode":"    kwargs: Additional keyword arguments to pass to the client's upsert method.\n    dense_embedding_key: name for the dense vector in the qdrant collection.\n    sparse_embedding_key: name for the sparse vector in the qdrant collection.\n  \"\"\"\n\n  connection_params: QdrantConnectionParameters\n  collection_name: str\n  timeout: Optional[int] = None\n  batch_size: int = DEFAULT_WRITE_BATCH_SIZE\n  max_batch_byte_size: int = DEFAULT_MAX_BATCH_BYTE_SIZE\n  kwargs: dict[str, Any] = field(default_factory=dict)\n  dense_embedding_key: str = \"dense\"\n  sparse_embedding_key: str = \"sparse\"\n\n  def __post_init__(self):\n    if not self.collection_name:\n      raise ValueError(\"Collection name must be provided\")\n    if self.batch_size <= 0:\n      raise ValueError(\"Batch size must be a positive integer\")\n\n  def create_write_transform(self) -> beam.PTransform[EmbeddableItem, Any]:\n    return _QdrantWriteTransform(self)\n\n  def create_converter(\n      self,\n  ) -> Callable[[EmbeddableItem], \"models.PointStruct\"]:\n    def convert(item: EmbeddableItem) -> \"models.PointStruct\":\n      if item.dense_embedding is None and item.sparse_embedding is None:\n        raise ValueError(\n            \"EmbeddableItem must have at least one embedding (dense or sparse)\")\n      vector = {}\n      if item.dense_embedding is not None:\n        vector[self.dense_embedding_key] = item.dense_embedding\n      if item.sparse_embedding is not None:\n        sparse_indices, sparse_values = item.sparse_embedding\n        vector[self.sparse_embedding_key] = models.SparseVector(\n            indices=sparse_indices,","sourceCodeStart":183,"sourceCodeEnd":219,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/python/apache_beam/ml/rag/ingestion/qdrant.py#L183-L219","documentation":"QdrantSinkConfig.__post_init__ validates that batch_size is a positive integer; zero or negative batch sizes (or non-int values that slip through typing) would produce empty or invalid upsert requests.","triggerScenarios":"Constructing the sink config with batch_size=0 (often intended as 'no batching'), a negative number, or an unset option that defaults to 0 instead of the library default.","commonSituations":"Passing batch_size from pipeline options where the user set 0 thinking it disables batching; type confusion where a None/0 parsed from YAML becomes the value; copy-paste tuning that left batch_size=-1.","solutions":["Set batch_size to a positive integer (e.g. 64 or 128)","To write items one at a time, use batch_size=1 rather than 0","If sourced from options, coerce and validate int(value) > 0 before constructing the config"],"exampleFix":"// before\nparams = QdrantWriteParameters(..., batch_size=0)\n// after\nparams = QdrantWriteParameters(..., batch_size=64)","handlingStrategy":"validation","validationCode":"batch_size = int(options.qdrant_batch_size)\nassert batch_size > 0, f\"batch_size must be > 0, got {batch_size}\"","typeGuard":"def is_valid_batch_size(n) -> bool:\n    return isinstance(n, int) and not isinstance(n, bool) and n > 0","tryCatchPattern":null,"preventionTips":["Remember 0 does not mean 'no batching' — use 1 instead","Coerce option values to int before passing them in","Use the library default (don't set batch_size) unless tuning"],"tags":["python","qdrant","configuration","batching"],"backgroundTag":"invalid-config-value","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-20T03:17:13.778Z"}