-
Notifications
You must be signed in to change notification settings - Fork 631
[Bug] Task editor gets stuck on "Saving..." when PATCH returns 400 {"error":"No updates provided"} #505
Description
Summary
When editing a task in Mission Control, the UI can get stuck showing "Saving..." if the frontend sends a task PATCH request that contains no actual changes.
The backend responds quickly with:
{"error":"No updates provided"}but the frontend appears not to clear its saving state for this case, leaving the UI in a perpetual loading state.
Impact
This makes task editing look broken even though the backend is healthy and other writes are succeeding.
It creates the impression that:
- the request is hanging
- the task was not saved
- Mission Control is unstable
In reality, this appears to be a frontend state-handling bug around no-op updates.
Reproduction
API-level reproduction
If a task is already in testing status, sending the same PATCH again returns:
PATCH /api/tasks/:id
Content-Type: application/json
{
"status": "testing"
}Response:
400 Bad Request{"error":"No updates provided"}An empty patch body behaves the same way:
PATCH /api/tasks/:id
Content-Type: application/json
{}Response:
{"error":"No updates provided"}UI-level reproduction
- Open a task detail page
- Trigger save with no meaningful changes, or cause the frontend to build an empty/no-op patch
- Frontend sends
PATCH /api/tasks/:id - Backend returns
400 {"error":"No updates provided"} - UI remains stuck on "Saving..."
Actual behavior
- Backend returns quickly
- Request does not hang
- UI remains in saving/loading state
Expected behavior
Any of the following would be acceptable:
Option A: Do not send empty patches
If the computed patch is empty, the frontend should:
- skip the request
- immediately clear saving state
- optionally show a subtle "No changes to save" message
Option B: Handle the backend response gracefully
If the backend returns:
{"error":"No updates provided"}the frontend should:
- clear saving state
- avoid leaving the UI in a perpetual loading state
- optionally show a non-fatal notice
Option C: Make backend no-op updates idempotent
The backend could return 200 OK for no-op task updates, e.g.:
{ "ok": true, "unchanged": true }This would make CLI/UI/automation flows easier to handle consistently.
Evidence collected
Backend is healthy
Direct API calls to Mission Control succeed and respond quickly.
Observed behavior:
GET /api/tasks/:id→200 OK- task reads return in ~20ms
- authenticated writes succeed when there is a real change
Auth is working
Using:
Authorization: Bearer <MC_API_TOKEN>the following operations succeeded:
- create activity
- create deliverable
- patch task status (when status actually changes)
Critical error payload
For no-op task updates, the backend returns:
{"error":"No updates provided"}This strongly suggests the frontend is not handling this response path correctly.
Likely root cause
High probability frontend state-management issue:
- UI sets
saving = true - frontend builds a patch object
- patch is empty or equivalent to current values
- request is still sent
- backend returns
400 {"error":"No updates provided"} - error path does not properly reset saving state
- UI remains stuck on "Saving..."
Suggested fix
Frontend minimal fix
- Prevent empty PATCH requests
- compare original task vs edited task
- if diff is empty, do not send request
- Always clear saving state in
finally
- success, failure, and no-op cases should all exit loading state
- Treat
No updates providedas a harmless no-op
- do not leave the page in an error-loading limbo
Example approach:
const patch = buildTaskPatch(originalTask, editedTask)
if (Object.keys(patch).length === 0) {
setSaving(false)
return
}
try {
await updateTask(taskId, patch)
} catch (err) {
if (getErrorMessage(err).includes("No updates provided")) {
// treat as harmless no-op
} else {
throw err
}
} finally {
setSaving(false)
}Optional backend improvement
Consider making no-op task updates idempotent instead of returning 400.
For example:
{ "ok": true, "unchanged": true }This would improve:
- automation ergonomics
- CLI stability
- frontend simplicity
- consistency with agent-driven workflows
Acceptance criteria
- Saving a task with no actual changes does not leave the UI stuck on "Saving..."
- Empty/no-op patches are either:
- not sent at all, or
- handled gracefully after response
- Saving state is always cleared
- Repeated save clicks do not leave the UI in a broken loading state
Related observation
Deliverables currently appear to be append-only and non-idempotent:
- repeated POSTs can create duplicate deliverable records
- no delete route was discovered from the exposed API surface
That is separate from this bug, but it reinforces the need for more defensive frontend request handling around retries and duplicate submissions.
Metadata
Metadata
Assignees
Labels
Type
Projects
Status