You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
If a legacy runFiber() finishes but deleting its bookkeeping row fails, the next recovery scan treats that leftover row as interrupted work and calls onFiberRecovered().
A custom recovery hook could repeat something that already happened, such as sending a message. The SDK does not automatically rerun the original function; the default hook only logs a warning.
How serious is it?
Low priority; raised by Devin in release PR #2251 as a pre-existing issue unrelated to that PR.
We reproduced the incorrect recovery callback with SQLite fault injection, but found no production reports of duplicate work caused by this exact bug.
Harm requires both a cleanup failure and a recovery hook that repeats work without checking whether it already happened. We expect this to be rare, but have no frequency data.
This affects legacy runFiber(), not the new Lifecycle/Tasks engine, which records completion before cleanup. Managed startFiber() runs with a saved terminal status are also protected. Think/AIChat still use legacy fibers for facet-hosted turns; top-level turns use Tasks.
History
Present since agents@0.10.0 (April 7, 2026), following #1256. #2244 preserves the successful result when cleanup fails; it did not introduce the underlying false recovery. This issue tracks the remaining problem separately from #2104.
Possible resolution
Record that the body finished so recovery can delete leftover rows without calling the hook. For facets, keep the parent's recovery registration until the child's row is deleted.
The existing cleanup-failure test checks the result and row cleanup, but should also check that the recovery hook was not called.
Alternatively, resolve this by safely retiring legacy fibers.Deprecation is contemplated, but remaining callers must migrate and existing runs must drain first. There is no committed removal date.
What happens
If a legacy
runFiber()finishes but deleting its bookkeeping row fails, the next recovery scan treats that leftover row as interrupted work and callsonFiberRecovered().A custom recovery hook could repeat something that already happened, such as sending a message. The SDK does not automatically rerun the original function; the default hook only logs a warning.
How serious is it?
Low priority; raised by Devin in release PR #2251 as a pre-existing issue unrelated to that PR.
This affects legacy
runFiber(), not the new Lifecycle/Tasks engine, which records completion before cleanup. ManagedstartFiber()runs with a saved terminal status are also protected. Think/AIChat still use legacy fibers for facet-hosted turns; top-level turns use Tasks.History
Present since
agents@0.10.0(April 7, 2026), following #1256. #2244 preserves the successful result when cleanup fails; it did not introduce the underlying false recovery. This issue tracks the remaining problem separately from #2104.Possible resolution
Record that the body finished so recovery can delete leftover rows without calling the hook. For facets, keep the parent's recovery registration until the child's row is deleted.
The existing cleanup-failure test checks the result and row cleanup, but should also check that the recovery hook was not called.
Alternatively, resolve this by safely retiring legacy
fibers. Deprecation is contemplated, but remaining callers must migrate and existing runs must drain first. There is no committed removal date.