Skip to content

An interrupted teardown hook leaves a managed environment retrying forever, with no backoff and no recovery command #4158

Description

@mattwyckhouse

Environment. bb 0.43.3 desktop; git-worktree provider; repositories with a
.bb-env-teardown.sh hook.

Symptom. After a host-daemon restart interrupts a teardown hook, the environment stays in
status: error, lifecycle.teardown.status: failed with the message
Environment hook outcome is unknown after interruption. Automatic cleanup is blocked; inspect the workspace before recovering it.
and is retried once per minute indefinitely. On one host 18 environments are in this state with
attempt counters between 2,981 and 8,305 (about 5.8 days at one attempt per minute), each attempt
costing a host RPC with a 6 s timeout; 10 of their worktrees still exist (7.6 GB) and 8 are
already gone, yet none can complete. bb guide environments documents that a lost hook blocks
cleanup and "requires inspection before recovery", but there is no recovery verb, no filter to
find such environments, and no bound on the retries.

Evidence (installed bundle server/dist/start-server.js).

  • cancelPendingEnvironmentHook (209864–209884): if the environment_hook_operations row has no
    finished_at, it sends environment.hook.cancel with TRANSPORT_GRACE_MS (6 s, 209894); when the
    host answers unknown it throws the message above before the finished_at update that
    follows, so the row stays pending.
  • runEnvironmentHook's catch awaits that cancel before logging "continuing removal"
    (209849–209857), so the throw escapes to runRemove.
  • runRemove (239037–239110) catches it and writes teardownStatus: "failed",
    retireAt: Date.now() + REMOVE_RETRY_MS (60 s, 239905). The lifecycle sweep re-enters as soon as
    retireAt passes (239186–239187), increments teardownAttempt (239189) and takes the identical
    path. No backoff, no cap, no terminal state.
  • Recovery: no route or CLI clears teardown_status for an environment; the only reset is the
    provisioning upsert (34561), which is not reachable as an operation. bb environment delete
    enters the same removal path.

Query to find affected rows. SELECT count(*) FROM environment_hook_operations WHERE finished_at IS NULL;
and SELECT id, teardown_attempt FROM environments WHERE teardown_status = 'failed';

Reproduction. Commit a .bb-env-teardown.sh that sleeps for a minute, archive the last thread
of a worktree environment, and restart the host daemon while the hook is running. The environment
enters teardown failed and retries every 60 s from then on.

Proposed fix.

  1. On the unknown branch, mark the hook operation finished with an unknown error (and record
    the message on the environment) so the next attempt can proceed to provider.remove; the
    guide already states there is no cross-restart process tracking, so the row cannot be resolved
    later anyway.
  2. Exponential backoff on the retry interval and a cap on teardownAttempt, after which the
    environment enters a terminal teardown: blocked state that stops the RPCs.
  3. bb environment recover <id> (clear the teardown state after confirming no live threads; treat
    a missing path as removed) and bb environment list --teardown failed.
  4. Docs: state the retry cadence (currently 60 s, no backoff) and the recovery procedure next to
    the existing sentence about the unknown-outcome block.

Filed from an audit of bb 0.43.3 by the Factory plugin (github.com/mattwyckhouse/bb-plugin-factory). Method, re-derived numbers and the adversarial review of this report: plans/076-host-sustainable-line/bb-core-issues/REVIEW.md in that repository.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    confirmed-reproBug reproduced again from a clean trusted checkout; see linked reportworkspacesWorktrees, environments, git, shells

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions