Skip to content

fix(automations): save-error banner cleared on failure (follow-up to #369)#371

Merged
mgoldsborough merged 1 commit into
mainfrom
fix/automation-save-error-banner
Jun 3, 2026
Merged

fix(automations): save-error banner cleared on failure (follow-up to #369)#371
mgoldsborough merged 1 commit into
mainfrom
fix/automation-save-error-banner

Conversation

@mgoldsborough
Copy link
Copy Markdown
Contributor

Follow-up to #369. A QA reviewer correctly found that the "surface update errors" half of #369 doesn't actually work — verified against source.

The bug

AutomationDetailView.saveField:

async function saveField(field, value) {
  setEditing(null);
  setError(null);
  try {
    await onUpdate(...);     // rejects
  } catch (err) {
    setError(err.message);   // sets the error
  }
  loadDetail();              // ← runs setError(null) (line 51) before its first await
}

When onUpdate rejects, the catch runs setError(message), then loadDetail() runs synchronously to its first await — executing setError(null). Both updates land in the same microtask continuation, React batches them, null wins, and the banner ({error && …}) never renders. (Even without batching, it's two sequential setErrors and null is last.) Net: a rejected save still looks like a silent no-op — the exact symptom #369 set out to fix.

The fix

Refresh only on success:

try {
  await onUpdate(...);
  loadDetail();            // success path only
} catch (err) {
  setError(err.message);   // persists; no refresh to clear it
}

On failure the error stays set; the field reverts because setEditing(null) closes the inline editor and re-renders the unchanged detail value.

Notes

  • The cap-raise half of fix(automations): raise iteration cap to 50, surface update errors #369 (15→50, default 5→25) was unaffected and is correct.
  • No regression test: the bundle UIs have no component-test harness (@testing-library); this React state-timing path can't be covered without standing up RTL. Verified manually against the batching trace; bun run verify:static green and the automations bundle UI builds clean.

…ilure

The error-surfacing fix from #369 was defeated by its own refresh call.
saveField set the error in its catch, then unconditionally called
loadDetail(), whose first synchronous statement is setError(null) (before
its await). Both updates landed in the same microtask continuation, React
batched them, null won, and the banner never rendered — so a rejected save
(e.g. an out-of-range maxIterations) still looked like a silent no-op, the
exact symptom #369 set out to fix.

Refresh only on success. On failure the error persists and the closed inline
editor re-renders the field at its unchanged saved value.

No regression test: the bundle UIs have no component-test harness
(@testing-library), so this React state-timing path can't be covered without
standing up RTL. Verified manually against the batching trace.
@mgoldsborough mgoldsborough added the qa-reviewed QA review completed with no critical issues label Jun 3, 2026
@mgoldsborough mgoldsborough merged commit 87da937 into main Jun 3, 2026
5 checks passed
@mgoldsborough mgoldsborough deleted the fix/automation-save-error-banner branch June 3, 2026 03:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

qa-reviewed QA review completed with no critical issues

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant