{"record":{"id":"ac49c344c3c8d117","repo":"HKUDS/Vibe-Trading","slug":"retry-number-must-be-at-least-1","errorCode":null,"errorMessage":"retry_number must be at least 1","messagePattern":"retry_number must be at least 1","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"agent/src/swarm/runtime.py","lineNumber":60,"sourceCode":"from src.swarm.presets import build_run_from_preset\nfrom src.swarm.store import SwarmStore\nfrom src.swarm.task_store import (\n    TaskStore,\n    resolve_dependencies,\n    topological_layers,\n    validate_dag,\n)\nfrom src.tools.mcp import invalidate_mcp_specs_cache\nfrom src.tools.redaction import redact_internal_paths\nfrom src.swarm.worker import agent_artifact_dir, clear_agent_artifacts, run_worker\n\nlogger = logging.getLogger(__name__)\n\n\ndef _worker_retry_delay_ceiling_s(retry_number: int) -> float:\n    \"\"\"Return the capped exponential ceiling for a one-based retry number.\"\"\"\n    if retry_number < 1:\n        raise ValueError(\"retry_number must be at least 1\")\n\n    config = get_env_config().swarm\n    base_delay = config.swarm_worker_retry_base_delay_s\n    max_delay = config.swarm_worker_retry_max_delay_s\n    exponent = min(retry_number - 1, 62)\n    return min(base_delay * (2**exponent), max_delay)\n\n\ndef _worker_retry_delay_s(retry_number: int) -> float:\n    \"\"\"Return an equal-jitter exponential delay for a worker-level retry.\n\n    Equal jitter keeps half of the exponential delay while spreading\n    concurrent swarm workers across the remaining half of the window.\n    \"\"\"\n    delay_ceiling = _worker_retry_delay_ceiling_s(retry_number)\n    return random.uniform(delay_ceiling / 2, delay_ceiling)\n\n","sourceCodeStart":42,"sourceCodeEnd":78,"githubUrl":"https://github.com/HKUDS/Vibe-Trading/blob/80ffdda44c5c4db0dd84d70e051cca591cea67df/agent/src/swarm/runtime.py#L42-L78","documentation":"_worker_retry_delay_ceiling_s computes exponential backoff for worker retries and requires retry_number to be one-based (1, 2, ...). Passing 0 or a negative number raises ValueError, since 2**(negative exponent) semantics would be wrong for a ceiling.","triggerScenarios":"Computing a delay for the attempt before the first retry (retry_number=0), or looping `for i in range(retries)` and passing i starting at 0.","commonSituations":"Off-by-one bugs in retry loops; mixing zero-based attempt counters with the one-based retry API.","solutions":["Pass the retry ordinal starting at 1 (first retry = 1)","If you have a zero-based attempt index, pass attempt+1"],"exampleFix":"# before\ndelay = _worker_retry_delay_ceiling_s(attempt)  # attempt starts at 0\n# after\ndelay = _worker_retry_delay_ceiling_s(attempt + 1)","handlingStrategy":"validation","validationCode":"retry_number = max(1, retry_number)","typeGuard":"def is_valid_retry_number(n) -> bool:\n    return isinstance(n, int) and n >= 1","tryCatchPattern":"try:\n    delay = _worker_retry_delay_ceiling_s(n)\nexcept ValueError:\n    delay = _worker_retry_delay_ceiling_s(1)","preventionTips":["Treat retry numbers as one-based throughout the codebase","Name loop variables retry_no starting at 1","Unit-test boundary retry_number=1"],"tags":["python","retry","off-by-one"],"backgroundTag":"invalid-argument-value","analyzedSha":"80ffdda44c5c4db0dd84d70e051cca591cea67df","analyzedAt":"2026-08-28T12:46:38.989Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}