Skip to content

Task UI spinner persists indefinitely due to status update race condition #1315

@blinkagent

Description

@blinkagent

Problem

The task UI spinner continues spinning indefinitely even when no activity has occurred in the task chat for a long time. This happens due to a race condition between status updates from the AI agent (via MCP) and AgentAPI's screen watcher.

Root Cause

When the AI agent reports "working" via MCP and AgentAPI later detects "idle" via the screen watcher, the updates can race. If the agent's "working" status arrives after AgentAPI's "idle" status, the UI gets stuck showing the spinner.

Additionally, the client-side queue predicate in cli/exp_mcp.go filters out duplicate status updates (same state/link/summary), which prevents AgentAPI from "reminding" Coder of the correct idle state.

Current Behavior

  1. Client-side deduplication (cli/exp_mcp.go lines 465-469) blocks duplicate updates:

    if report.state == lastReport.state &&
        report.link == lastReport.link &&
        report.summary == lastReport.summary {
        return report, false
    }
  2. Server-side notification filtering (coderd/workspaceagents.go lines 492-496) prevents notification spam for same-state updates.

  3. The server always inserts status records into the database, but if duplicates are filtered client-side, updates never reach the server to correct the UI.

Proposed Solution

Modify the client-side queue predicate to allow periodic "reminder" updates through, even if the state hasn't changed. For example:

// Allow duplicate state through if enough time has passed (e.g. 30s)
if time.Since(lastReport.timestamp) > 30*time.Second {
    lastReport = report
    return report, true
}

This would:

  • Allow AgentAPI to periodically re-send the current state to correct any race condition issues
  • Still benefit from server-side notification deduplication (no user spam)
  • Fix the stuck spinner issue by ensuring the UI eventually reflects the correct state

Notes

  • The UI uses polling via watchWorkspace(), so status updates sent to the server should be reflected
  • The existing code already preserves previous message/link when new updates have empty fields (PATCH-like semantics), so this change would be additive

Created on behalf of @johnstcn

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions