fix(worker): 节点重试预算键被「任一节点成功」反复清零——确定性失败节点无限重投、执行永不终态
Nobody has claimed this yet.
Assessment
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Newbie friendliness
- 50/100
Research direction
Start in plaita/server/flow_worker.py: _reset_node_retry_counter (around lines 618-633) is called unconditionally after any node advances, near line 1851, and _node_failure_retry_decision (around lines 637-672) increments the same key. Keep the G1 manual-retry reset near line 1639 unchanged. Build a flow where node X always fails, node Y always succeeds and loops back to X, then check that the retry counter reaches 5/5, 'node retry budget exhausted' is logged once, and the execution ends in error.
Written by the indexing model from the issue text.
Description
优先级 P1 · 依赖:无
基线 HEAD = 65f48f2
Summary
节点重试预算的计数键会被「任一节点成功推进」清零,于是「确定性失败 + 环回重投」的节点永远拿不回累积值——每次重投都从 1/5 重新起算,预算耗尽分支从未触发,执行可以无限重投而不终态。
- 代码证据:
plaita/server/flow_worker.py:1851——每一次run_distributed步进成功(任意节点)后无条件调用_reset_node_retry_counter(execution_id);该函数(:618-633)DEL plaita:execution:noderetry:<execution_id>。而预算判定_node_failure_retry_decision(:637-672)用的是同一键INCR后的值(:656)。即:不同节点的成功与同一节点的连续失败共享一个会被清空的键。 - 运行期证据(计数分布):2026-10-09 本机 worker-mac.log 中
第 N/5 次重试的出现次数为1/5× 598,2/5/3/5/4/5/5/5× 0;全日志节点重试预算耗尽× 0。grep "2026-10-09" ~/.plaita-console/worker-mac.log | grep -oE "第 [0-9]/5 次重试" | sort | uniq -c grep -c "节点重试预算耗尽" ~/.plaita-console/worker-mac.log # → 0 - 运行期证据(键不累积):对当时正在循环的执行
fbc93f1da1754a8d9a9c3ea8807930f4,60 秒内每 3 秒GET plaita:execution:noderetry:fbc93f1da1754a8d9a9c3ea8807930f4→ 全程 nil;同窗口grep -c "执行 fbc93f1d… 节点执行失败"前后差 = 1(确实失败了一次)。失败发生了,计数键却不存在。 - 触发场景:impl 节点确定性失败(本次诱因是 GLM 5 小时限额:
HTTP 429 {"error":{"code":"1308","message":"[1308][已达到 5 小时的使用上限。您的限额将在 2026-10-09 18:11:22 重置。]"}})。重投的同体新副本被 worker 重放时,同一次run_distributed里仍有别的节点推进成功(pre/gates/分支/错误处理节点)→ 键被清零 → impl 再次失败时又从1/5起算。
影响
- 瞬态故障 → 无界重投风暴:任何一个节点的确定性失败(provider 429/401、依赖不一致、门恒红)都能让 execution 永远停在 running,keeper 收不到终态、在途槽位不释放、DLQ/日志/账目全被污染。
- 今日实测代价:6 个在途 run 持续 90 分钟零落地(近 90min 28 次派发 / 0 落地),worker-mac.log 胀到 8.8MB(
AgentRunError: executor 'recursive' exited 12387 次、exited 143539 次),并向 GLM 持续打 429;pipeline_max_in_flight=6的槽位被 6 个永不收敛的执行长期占满。 - 预算机制形同虚设:设计意图是「连续失败 5 次即终态化」,实际 0 次触发;失败只能靠别处(人工 cancel / zombie reap)终结。
建议
- 预算键改按
(execution_id, node_id)计,且只在该节点自身成功推进时清零;或在此之外加一条「同一执行累计重投次数」上限(与节点维度独立,防环回场景绕过)。 - 保留现有语义:G1 人工 retry 唤醒时的清零(
:1639)不变——那是「拿全新预算」,与本缺陷无关。 - 验收(可断言):
- 构造「节点 X 恒失败、节点 Y 恒成功且流程环回 X」的 flow,投递执行 → 断言 X 的计数键达到预算值、日志出现恰好一次
节点重试预算耗尽、执行终态化error; - 同用例重复投递 → 断言不再出现
第 1/5 次重试无限循环(重投次数有界); - 回归:不同节点交替失败的场景中,节点 B 的首次失败仍应拿到完整预算(现注释所述意图不变)。
- 构造「节点 X 恒失败、节点 Y 恒成功且流程环回 X」的 flow,投递执行 → 断言 X 的计数键达到预算值、日志出现恰好一次
边界
- 本单只针对「预算键被非本节点的成功清零」。相邻缺陷另单:编号 50(重投载体被租约冲突 ack 吃掉)、编号 52(重试耗尽后 console 终态滞后)、编号 47(reclaim 不查活跃租约的 churn)——机制不同,不合并。
- 不改队列层 delivery_count 语义(
task_queue.pyreclaim 上报的是 XCLAIM 前的 times_delivered,本单沿用 worker 侧计数键的设计选择)。
- Dominant language
- Python
- Stars
- 0
- Forks
- 1
- Avg merge
- 3h 53m
- Merged PRs (30d)
- 3
Getting set up
This project ships no dev container, Dockerfile or contributing guide, so setting up is up to you: start from its README, and see our first-contribution guide for the general steps.
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from jeffkit/plaita
-
Difficulty 4/5 3-5 days Newbie friendliness 42/100
-
Difficulty 4/5 3-5 days Newbie friendliness 48/100
-
Difficulty 5/5 Over a week Newbie friendliness 24/100
-
Difficulty 4/5 3-5 days Newbie friendliness 8/100
Similar issues
-
Deferred from #1869: Complete the companion pytest guardrail update noted in the PR description...Open
Difficulty 1/5 Under an hour Newbie friendliness 95/100
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
NousResearch/hermes-agent#140958 ·
Maintainers usually reply within 1 day
-
Bug triage/confirmed
Difficulty 2/5 Half a day Newbie friendliness 85/100
agentscope-ai/agentscope#3355 ·
Maintainers usually reply within 2 days
-
Difficulty 1/5 Under an hour Newbie friendliness 95/100
ethereum/execution-specs#3859 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
Maintainers usually reply within 1 day