Skip to content

fix(fleet): block agent update when node unreachable#195

Merged
TerrifiedBug merged 2 commits intomainfrom
fix/block-agent-update-unreachable
Apr 28, 2026
Merged

fix(fleet): block agent update when node unreachable#195
TerrifiedBug merged 2 commits intomainfrom
fix/block-agent-update-unreachable

Conversation

@TerrifiedBug
Copy link
Copy Markdown
Owner

@TerrifiedBug TerrifiedBug commented Apr 28, 2026

Summary

Fixes Notion bug: "Should not be able to try update agents when they are unreachable."

Previously, the "Update available" badge was always clickable when a newer agent version existed, regardless of node reachability. Triggering an update on an unreachable node could not actually deliver the action, queued a stale `pendingAction`, and surfaced a confusing failure state.

  • Backend (`fleet.triggerAgentUpdate`): throws `FAILED_PRECONDITION` when `node.status === "UNREACHABLE"`
  • Frontend (fleet table): renders the "Update available" badge as disabled (opacity-50, cursor-not-allowed) with a tooltip explaining the agent must reconnect first

Defense in depth — both layers reject the action.

Test plan

  • Mark a node UNREACHABLE → "Update available" badge is greyed out, tooltip explains why
  • Click the disabled badge → no dialog opens
  • Direct API call to triggerAgentUpdate on UNREACHABLE node → returns FAILED_PRECONDITION
  • Healthy node still updates normally

Greptile Summary

This PR adds a defense-in-depth guard preventing agent updates when the target node is UNREACHABLE: the backend throws an error and the frontend renders a visually disabled badge with a tooltip. The frontend change is correct, but the backend uses FAILED_PRECONDITION — a gRPC status code that is not part of tRPC v11's TRPC_ERROR_CODE_KEY type — which will cause tsc --noEmit to fail in CI. The fix is a one-word change to PRECONDITION_FAILED.

Confidence Score: 3/5

Not safe to merge as-is — the backend uses an invalid tRPC error code that will fail type-checking in CI.

A P1 syntax error in the backend (FAILED_PRECONDITION vs PRECONDITION_FAILED) would break CI type-checking. The fix is trivial (one word), and the rest of the PR logic is correct, but the build must pass before merging.

src/server/routers/fleet.ts — invalid tRPC error code on line 417.

Important Files Changed

Filename Overview
src/server/routers/fleet.ts Adds UNREACHABLE guard to triggerAgentUpdate, but uses FAILED_PRECONDITION which is not a valid tRPC error code — will fail tsc --noEmit in CI.
src/app/(dashboard)/fleet/page.tsx Adds a disabled, non-clickable "Update available" badge with a tooltip for UNREACHABLE nodes; ordering relative to DOCKER check is correct and logic is sound.

Sequence Diagram

sequenceDiagram
    actor User
    participant UI as Fleet Page (frontend)
    participant API as fleet.triggerAgentUpdate (tRPC)
    participant DB as PostgreSQL

    User->>UI: Views node with update available
    alt node.status === "UNREACHABLE"
        UI-->>User: Disabled badge + tooltip (wait for reconnect)
        Note over UI: No click handler — dialog never opens
    else node is reachable
        User->>UI: Clicks "Update available" badge
        UI->>API: triggerAgentUpdate({ nodeId, ... })
        API->>DB: findUnique(nodeId)
        DB-->>API: node
        alt node.status === "UNREACHABLE" (API guard)
            API-->>UI: TRPCError PRECONDITION_FAILED
            UI-->>User: Error toast
        else node OK
            API->>DB: update pendingAction = self_update
            DB-->>API: updated node
            API-->>UI: success
            UI-->>User: Update initiated
        end
    end
Loading

Fix All in Claude Code Fix All in Codex

Prompt To Fix All With AI
This is a comment left during a code review.
Path: src/server/routers/fleet.ts
Line: 417-422

Comment:
**Invalid tRPC error code — `FAILED_PRECONDITION` does not exist**

`FAILED_PRECONDITION` is a gRPC status code, not a tRPC error code. tRPC v11's `TRPC_ERROR_CODE_KEY` type does not include this value, so TypeScript will reject this at compile time and `tsc --noEmit` (run in CI) will fail. The correct tRPC code for "operation rejected because a precondition is not met" is `PRECONDITION_FAILED`.

```suggestion
      if (node.status === "UNREACHABLE") {
        throw new TRPCError({
          code: "PRECONDITION_FAILED",
          message:
            "Cannot update an unreachable agent — wait for it to reconnect before retrying",
        });
      }
```

How can I resolve this? If you propose a fix, please make it concise.

Reviews (1): Last reviewed commit: "fix(fleet): block agent self-update when..." | Re-trigger Greptile

Greptile also left 1 inline comment on this PR.

Triggering an agent update when the node is unreachable can't reach the
agent, leaves a pending action queued, and surfaces a confusing failure
state to the user.

- Backend: triggerAgentUpdate throws FAILED_PRECONDITION when
  node.status === "UNREACHABLE"
- Frontend: render "Update available" as a disabled badge with a
  tooltip explaining the agent must be reachable before updating
@github-actions github-actions Bot added the fix label Apr 28, 2026
Comment on lines +417 to +422
throw new TRPCError({
code: "FAILED_PRECONDITION",
message:
"Cannot update an unreachable agent — wait for it to reconnect before retrying",
});
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Invalid tRPC error code — FAILED_PRECONDITION does not exist

FAILED_PRECONDITION is a gRPC status code, not a tRPC error code. tRPC v11's TRPC_ERROR_CODE_KEY type does not include this value, so TypeScript will reject this at compile time and tsc --noEmit (run in CI) will fail. The correct tRPC code for "operation rejected because a precondition is not met" is PRECONDITION_FAILED.

Suggested change
throw new TRPCError({
code: "FAILED_PRECONDITION",
message:
"Cannot update an unreachable agent — wait for it to reconnect before retrying",
});
}
if (node.status === "UNREACHABLE") {
throw new TRPCError({
code: "PRECONDITION_FAILED",
message:
"Cannot update an unreachable agent — wait for it to reconnect before retrying",
});
}
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/server/routers/fleet.ts
Line: 417-422

Comment:
**Invalid tRPC error code — `FAILED_PRECONDITION` does not exist**

`FAILED_PRECONDITION` is a gRPC status code, not a tRPC error code. tRPC v11's `TRPC_ERROR_CODE_KEY` type does not include this value, so TypeScript will reject this at compile time and `tsc --noEmit` (run in CI) will fail. The correct tRPC code for "operation rejected because a precondition is not met" is `PRECONDITION_FAILED`.

```suggestion
      if (node.status === "UNREACHABLE") {
        throw new TRPCError({
          code: "PRECONDITION_FAILED",
          message:
            "Cannot update an unreachable agent — wait for it to reconnect before retrying",
        });
      }
```

How can I resolve this? If you propose a fix, please make it concise.

Fix in Claude Code Fix in Codex

@github-actions github-actions Bot added fix and removed fix labels Apr 28, 2026
@TerrifiedBug TerrifiedBug merged commit 3b12d1b into main Apr 28, 2026
10 checks passed
@TerrifiedBug TerrifiedBug deleted the fix/block-agent-update-unreachable branch April 28, 2026 08:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant