{"record":{"id":"4d122bc82ce5317a","repo":"xai-org/x-algorithm","slug":"region-region-r-must-list-at-least-one-broker-4d122b","errorCode":null,"errorMessage":"Region {region!r} must list at least one broker","messagePattern":"Region (.+?) must list at least one broker","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"grox/libs/kafka_cli/multi_region_producer.py","lineNumber":28,"sourceCode":"\nlogger = logging.getLogger(__name__)\n\nRETRY_FAILED_REGION_INTERVAL_SEC = 60\n\n\nclass MultiRegionKafkaProducerConfig(BaseModel):\n    topic: str\n    clusters: dict[str, list[str]]\n    acks: int | str = Field(default=1)\n    request_timeout_ms: int = Field(default=30000)\n\n    @model_validator(mode=\"after\")\n    def _validate(self) -> \"MultiRegionKafkaProducerConfig\":\n        if not self.clusters:\n            raise ValueError(\"`clusters` must contain at least one region\")\n        for region, brokers in self.clusters.items():\n            if not brokers:\n                raise ValueError(f\"Region {region!r} must list at least one broker\")\n        if self.acks not in (0, 1, \"all\"):\n            raise ValueError(f\"acks must be 0, 1, or 'all', got {self.acks!r}\")\n        return self\n\n\nclass MultiRegionKafkaProducer:\n    def __init__(self, config: MultiRegionKafkaProducerConfig):\n        self.config = config\n        self.topic: str = config.topic\n        self._producers: dict[str, AIOKafkaProducer] = {}\n        self._region_retry_task: asyncio.Task | None = None\n\n    async def start(self):\n        regions = list(self.config.clusters.items())\n        try:\n            results = await asyncio.gather(\n                *[self._start_region(region, brokers) for region, brokers in regions],\n                return_exceptions=True,","sourceCodeStart":10,"sourceCodeEnd":46,"githubUrl":"https://github.com/xai-org/x-algorithm/blob/24c60942c5c5fdad3a6addffb4c6e6d2f228f04f/grox/libs/kafka_cli/multi_region_producer.py#L10-L46","documentation":"The producer's _validate validator requires each region in clusters to map to at least one broker address. An empty broker list for any region fails config construction with a message naming the offending region.","triggerScenarios":"MultiRegionKafkaProducerConfig with a region like {'us': []}; typically from per-region broker templating or discovery that returned nothing for one region.","commonSituations":"New region enabled in config before brokers are provisioned; DNS-based broker lists that resolved empty at render time; typo'd region key shadowing the populated one.","solutions":["Fill in real broker addresses for the failing region or delete that region entry.","If brokers are discovered dynamically, fail discovery loudly rather than emitting an empty list.","Add a config lint that every clusters value is a non-empty list of host:port strings."],"exampleFix":"# before\ncfg = MultiRegionKafkaProducerConfig(clusters={'us': ['b:9092'], 'eu': []})  # ValueError\n\n# after\ncfg = MultiRegionKafkaProducerConfig(clusters={'us': ['b:9092'], 'eu': ['eu-b:9092']})","handlingStrategy":"validation","validationCode":"clusters = {r: b for r, b in raw.items() if b}\ncfg = MultiRegionKafkaProducerConfig(clusters=clusters)","typeGuard":null,"tryCatchPattern":"try:\n    cfg = MultiRegionKafkaProducerConfig(clusters=raw)\nexcept ValueError as e:\n    logger.error('producer cluster config invalid: %s', e)  # names region\n    raise","preventionTips":["Require non-empty broker lists per region in config linting","Test config rendering per environment before deploy"],"tags":["kafka","pydantic","producer","brokers"],"backgroundTag":"schema-validation-failed","analyzedSha":"24c60942c5c5fdad3a6addffb4c6e6d2f228f04f","analyzedAt":"2026-08-28T11:40:14.686Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}