Skip to content

Retry install's conditional SSA apply when its own controllers win the race - #15

Merged
josephschorr merged 1 commit into
mainfrom
fix/install-ssa-conflict-retry
Oct 2, 2026
Merged

josephschorr merged 1 commit into
mainfrom
fix/install-ssa-conflict-retry

Conversation

@josephschorr

Copy link
Copy Markdown
Member

The flake

TestOapExportPackInstall_WithSpiceDB failed "first Install" three times across recent CI runs:

install: apply MCPServer/widget-mcp: ssa-apply MCPServer/widget-mcp: Operation cannot be fulfilled on
mcpservers.agentprimitives.authzed.com "widget-mcp": the object has been modified; please apply your
changes to the latest version and try again

— each time on whichever resource the operator reconciled first (MCPServer once, AgentIdentity twice). The varying resource is the tell: a race, not a deterministic break.

Root cause

applyPreparedObject Creates an object, then ssaApply applies it conditional on the Create-time (or Prepare-time) resourceVersion — deliberately, so disappearance or replacement fails closed. But the object's own controller watches these kinds and routinely writes to the fresh object (a status condition, a finalizer) in the window between that observation and the apply. When the controller's write lands first, the conditional apply conflicts and the whole install aborts, with no retry.

The fix

Treat a resourceVersion conflict as the recheck it is rather than as proof of foul play: re-read the object, and if the UID still matches the one this run approved, retry the apply on the current resourceVersion (retry.RetryOnConflict, bounded). A different UID — a same-name replacement mid-install — or a failed re-read still fails closed, which is the property the conditional apply exists for. The wizardrun applier shares the error string but stamps no resourceVersion, so it cannot hit this class and is untouched.

Verification

  • Three new fake-client tests (apply_conflict_retry_test.go): a single lost race retries to success, a replaced UID aborts with no second apply attempt, a never-resolving conflict surfaces after a bounded number of tries. All three watched failing before the fix — the first reproduces the CI error byte-for-byte.
  • mage test:unit, mage test:integration, mage test:e2e: all exit 0 locally.
  • go test -tags=e2e -count=2 -run '^TestOapExportPackInstall_WithSpiceDB$' ./test/e2e/scenarios/install/: pass.

…e race

applyPreparedObject Creates an object, then ssaApply server-side-applies
it conditional on the Create-time (or Prepare-time) resourceVersion so
that disappearance or replacement fails closed. But the object's own
controller watches these kinds and routinely writes to the fresh object
— a status condition, a finalizer — in the window between that
observation and the apply. Losing that race surfaced as:

    install: apply MCPServer/widget-mcp: ssa-apply MCPServer/widget-mcp:
    Operation cannot be fulfilled on ... the object has been modified

and aborted the whole install. TestOapExportPackInstall_WithSpiceDB hit
this three times across recent CI runs, each time on whichever resource
the operator reconciled first (MCPServer once, AgentIdentity twice).

A bare resourceVersion conflict is not by itself foul play, so treat it
as the recheck it is: re-read the object, and if the UID still matches
the one this run approved, retry the apply on the current
resourceVersion (retry.RetryOnConflict, bounded). A different UID — a
same-name replacement mid-install — or a failed re-read still fails
closed, which is the property the conditional apply exists for.

Three fake-client tests pin the behavior: a single lost race retries to
success, a replaced UID aborts without a second apply attempt, and a
conflict that never resolves surfaces after a bounded number of tries.
mage test:unit, test:integration, and test:e2e all pass locally.
@vercel

vercel Bot commented Oct 1, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
openagentprimitives Ready Ready Preview Oct 1, 2026 4:26am UTC

Request Review

@josephschorr
josephschorr merged commit b101ba4 into main Oct 2, 2026
20 of 23 checks passed

This branch was successfully deployed

1 active deployment
Preview — b6cbec5f Deployed Oct 1, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant