{"record":{"id":"7bbd5191eb2efe30","repo":"python/cpython","slug":"parties-must-be-1","errorCode":null,"errorMessage":"parties must be >= 1","messagePattern":"parties must be >= 1","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"Lib/asyncio/locks.py","lineNumber":485,"sourceCode":"    FILLING = 'filling'\n    DRAINING = 'draining'\n    RESETTING = 'resetting'\n    BROKEN = 'broken'\n\n\nclass Barrier(mixins._LoopBoundMixin):\n    \"\"\"Asyncio equivalent to threading.Barrier\n\n    Implements a Barrier primitive.\n    Useful for synchronizing a fixed number of tasks at known synchronization\n    points. Tasks block on 'wait()' and are simultaneously awoken once they\n    have all made their call.\n    \"\"\"\n\n    def __init__(self, parties):\n        \"\"\"Create a barrier, initialised to 'parties' tasks.\"\"\"\n        if parties < 1:\n            raise ValueError('parties must be >= 1')\n\n        self._cond = Condition() # notify all tasks when state changes\n\n        self._parties = parties\n        self._state = _BarrierState.FILLING\n        self._count = 0       # count tasks in Barrier\n\n    def __repr__(self):\n        res = super().__repr__()\n        extra = f'{self._state.value}'\n        if not self.broken:\n            extra += f', waiters:{self.n_waiting}/{self.parties}'\n        return f'<{res[1:-1]} [{extra}]>'\n\n    async def __aenter__(self):\n        # wait for the barrier reaches the parties number\n        # when start draining release and return index of waited task\n        return await self.wait()","sourceCodeStart":467,"sourceCodeEnd":503,"githubUrl":"https://github.com/python/cpython/blob/bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6/Lib/asyncio/locks.py#L467-L503","documentation":"asyncio.Barrier requires at least one participating task; parties < 1 makes wait() unsatisfiable (the barrier could never fill), so __init__ raises ValueError('parties must be >= 1') immediately.","triggerScenarios":"asyncio.Barrier(0) or Barrier(-n); computing parties from a shard count, worker count, or config that can be zero (e.g. Barrier(num_replicas) with none configured).","commonSituations":"Config-driven fan-out where a component count of 0 is possible; deriving parties from len(empty_list); environment-specific deployments (local dev with 0 workers) passing 0 through.","solutions":["Validate/derive parties with max(1, n) only if 1-party semantics are acceptable, else reject the config earlier","Fail fast with a descriptive config error before constructing the barrier","Skip barrier coordination entirely when there are fewer than 2 participants (a 1-party barrier is a no-op)"],"exampleFix":"# before\nbarrier = asyncio.Barrier(cfg.worker_count)  # 0 -> ValueError\n\n# after\nif cfg.worker_count < 1:\n    raise ConfigError('worker_count must be >= 1')\nbarrier = asyncio.Barrier(cfg.worker_count)","handlingStrategy":"validation","validationCode":"if not isinstance(parties, int) or parties < 1:\n    raise ValueError(f'barrier parties must be >= 1, got {parties!r}')\nbarrier = asyncio.Barrier(parties)","typeGuard":"def is_valid_barrier_parties(n) -> bool:\n    return isinstance(n, int) and n >= 1","tryCatchPattern":null,"preventionTips":["Validate worker/replica counts before building barriers","Treat a 1-party barrier as a no-op and skip it","Reject zero-count configs at startup with explicit messages"],"tags":["asyncio","barrier","validation","configuration"],"backgroundTag":null,"analyzedSha":"bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6","analyzedAt":"2026-08-14T22:01:13.976Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}