Skip to content

[bug] Task cancel/delete/read routes still dispatch through stale default runtime rows #218

Closed

Description

@serge-ivo

Problem

Some task routes still dispatch to the stale default runtime row instead of the live, pin-aware runner node.

The approve route documents and uses the correct behavior:

  • platform/workers/api/src/routes/instances.ts:1125 says paused tasks must reach the LIVE runner.
  • platform/workers/api/src/routes/instances.ts:1127 uses requireLiveRuntime(...).

But nearby routes still use the old default-row helpers:

  • GET /tasks/:taskId uses requireRuntime(...) at platform/workers/api/src/routes/instances.ts:1093.
  • DELETE /tasks/:taskId uses getRuntime(...) at platform/workers/api/src/routes/instances.ts:1174.
  • POST /tasks/:taskId/cancel uses requireRuntime(...) at platform/workers/api/src/routes/instances.ts:1186.
  • /task-events also refreshes through getRuntime(...) at platform/workers/api/src/routes/instances.ts:1208.

On multi-machine accounts, instance_runtimes can point at a disconnected/default runner while the active task lives on a node-scoped relay. Approve was fixed for this exact class of bug, but cancel/delete/read/event refresh still diverge.

Impact

Users can see a task as active, then cancel/delete it and have the request hit the wrong relay or no-op against a stale runner. The board mirror may hide a task while the real runner keeps working, or task detail/event refresh may show stale data even though the live node is connected.

Expected Fix

Route all live task operations through the same live, pin-aware path:

  • Use requireLiveRuntime(...) for mutating runner task operations.
  • For reads/events, either use getBoundRunnerConn/live runtime when refreshing or skip refresh and serve the mirror when no live node exists.
  • Keep runner-less mirrored tickets working as they do today.

Acceptance Criteria

  • Cancel/delete reaches the same runner node that approve/create uses.
  • A pinned runner that is offline returns a clear offline response rather than dispatching to another/stale row.
  • Tests cover two registered nodes where the default row is stale and the live node owns the task.

Activity

  1. added
    bugSomething isn't working
    browser-agentsBrowser automation generalization
    backendBackend / Worker / API work
    on Aug 5, 2026
  2. serge-ivo commented on Aug 6, 2026

    @serge-ivo
    ContributorAuthor

    Fixed in de2505f.

    The root cause worth recording: the reads reached for getRuntime because it was the only non-throwing option — requireLiveRuntime throws, and a read that must fall back to the mirror can't use it. So the shape of the helper pair pushed callers onto the stale default row.

    Added getLiveRuntime, the missing non-throwing half (mirroring getRuntime/requireRuntime). Now:

    • POST /tasks/:id/cancel → requireLiveRuntime: reaches the live node or returns a clear offline response, instead of dispatching at a dead relay and reporting a cancel that never happened.
    • GET /tasks/:id → requireLiveRuntime inside the existing try, so no live runner falls through to the mirror as before.
    • DELETE and /task-events → getLiveRuntime, mirror fallback unchanged.

    Runner-less mirrored tickets behave exactly as before.

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

    backendBackend / Worker / API workbrowser-agentsBrowser automation generalizationbugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions