{"record":{"id":"1c37738b84e8267a","repo":"xai-org/x-algorithm","slug":"num-shards-must-be-0-got-num-shards","errorCode":null,"errorMessage":"num_shards must be > 0, got {num_shards}","messagePattern":"num_shards must be > 0, got (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"phoenix/xrex/data/streaming/kafkaconsumer.py","lineNumber":473,"sourceCode":"            partitions = await force_kafka_metadata_update(consumer, topic)\n        if not partitions:\n            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\"","sourceCodeStart":455,"sourceCodeEnd":491,"githubUrl":"https://github.com/xai-org/x-algorithm/blob/24c60942c5c5fdad3a6addffb4c6e6d2f228f04f/phoenix/xrex/data/streaming/kafkaconsumer.py#L455-L491","documentation":"Internal validation in _range_partitions: the sharding math requires at least one shard. num_shards <= 0 (often 0 from an uninitialized/derived value) makes partition range computation meaningless, so a ValueError is raised immediately.","triggerScenarios":"Calling handle_topic_offset or _consume_multi_consumer with num_shards=0 (e.g. num_servers or world_size computed as 0), or a negative shard count passed via config/CLI.","commonSituations":"Distributed launcher returned world_size 0 because the process group was not initialized; num_shards derived from gRPC num_servers=0; CLI flag parsed with a default of 0 and never set.","solutions":["Trace where num_shards comes from and ensure it is a positive integer (typically world_size or number of server shards).","Add a config validation step at startup: assert num_shards >= 1 before entering the consume path.","If derived from gRPC CheckState (num_servers), check the dispatcher service returned sane dimensions."],"exampleFix":"# before\npartition_ids = _range_partitions(total_partitions, shard_index, num_shards=0)\n\n# after\nassert num_shards >= 1, f\"num_shards must be >= 1, got {num_shards}\"\npartition_ids = _range_partitions(total_partitions, shard_index, num_shards)","handlingStrategy":"validation","validationCode":"if not isinstance(num_shards, int) or num_shards < 1:\n    raise ConfigError(f\"num_shards must be a positive int, got {num_shards!r}\")","typeGuard":"def is_valid_shard_config(shard_index: int, num_shards: int) -> bool:\n    return isinstance(num_shards, int) and num_shards > 0 and 0 <= shard_index < num_shards","tryCatchPattern":null,"preventionTips":["Validate distributed config (world_size, num_shards) before entering consume loops.","Fail fast at CLI/config parse time on non-positive shard counts."],"tags":["validation","sharding","kafka","config"],"backgroundTag":"invalid-argument-validation","analyzedSha":"24c60942c5c5fdad3a6addffb4c6e6d2f228f04f","analyzedAt":"2026-08-28T11:40:14.686Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}