{"record":{"id":"f691d8e0c5ec06a8","repo":"xai-org/x-algorithm","slug":"total-partitions-must-be-0-got-total-partitio","errorCode":null,"errorMessage":"total_partitions must be >= 0, got {total_partitions}","messagePattern":"total_partitions must be >= 0, got (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"phoenix/xrex/data/streaming/kafkaconsumer.py","lineNumber":475,"sourceCode":"            available = await consumer.topics()\n            raise ValueError(\n                f\"No partitions found for topic '{topic}'. Available topics: {available}\"\n            )\n        count = len(partitions)\n        rank_logger.info(f\"Discovered {count} partitions for topic '{topic}' from Kafka metadata.\")\n        return count\n    finally:\n        try:\n            await consumer.stop()\n        except asyncio.CancelledError:\n            pass\n\n\ndef _range_partitions(total_partitions: int, shard_index: int, num_shards: int) -> list[int]:\n    if num_shards <= 0:\n        raise ValueError(f\"num_shards must be > 0, got {num_shards}\")\n    if total_partitions < 0:\n        raise ValueError(f\"total_partitions must be >= 0, got {total_partitions}\")\n    start = shard_index * total_partitions // num_shards\n    end = (shard_index + 1) * total_partitions // num_shards\n    return list(range(start, end))\n\n\nasync def handle_topic_offset(\n    consumer: AIOKafkaConsumer,\n    topic: str,\n    shard_index: int,\n    num_shards: int,\n    reset_to_latest: bool,\n    seek_to_timestamp_ms: int | None = None,\n    seek_to_offset: dict[int, int] | None = None,\n) -> list[TopicPartition]:\n    assert seek_to_timestamp_ms is None or seek_to_offset is None, (\n        \"seek_to_timestamp_ms and seek_to_offset cannot both be set\"\n    )\n    assert not (seek_to_timestamp_ms is not None and reset_to_latest), (","sourceCodeStart":457,"sourceCodeEnd":493,"githubUrl":"https://github.com/xai-org/x-algorithm/blob/24c60942c5c5fdad3a6addffb4c6e6d2f228f04f/phoenix/xrex/data/streaming/kafkaconsumer.py#L457-L493","documentation":"Validation in _range_partitions: total_partitions (the partition count discovered for the topic) must be non-negative. A negative value indicates corrupted or nonsensical metadata being passed into the shard-range math, so the function refuses to compute a range.","triggerScenarios":"handle_topic_offset or _consume_multi_consumer passing a negative partition count, typically from a bad len(partitions) path, an overridden total_partitions config set to -1, or arithmetic that underflowed.","commonSituations":"Manual override of partition count in config with -1 as 'auto/unset' sentinel; a code path computing total_partitions = something - something_else that went negative.","solutions":["Check any manually configured partition count and set it to the real topic partition count or let discovery fill it in.","Log total_partitions right before the call to find where the negative value originates.","Fix the discovery/computation upstream so only discovered non-negative counts reach _range_partitions."],"exampleFix":"# before\ntotal_partitions = configured.get(\"partitions\", -1)\n\n# after\ntotal_partitions = configured.get(\"partitions\") or len(await discover_partition_count(consumer, topic))","handlingStrategy":"validation","validationCode":"assert isinstance(total_partitions, int) and total_partitions >= 0, total_partitions","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Prefer discovering partition counts from Kafka rather than manual config.","Treat -1 sentinels at config boundary, never inside sharding math."],"tags":["validation","sharding","kafka"],"backgroundTag":"invalid-argument-validation","analyzedSha":"24c60942c5c5fdad3a6addffb4c6e6d2f228f04f","analyzedAt":"2026-08-28T11:40:14.686Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}