Approval decision fails with 409 when the Confluence approvalPath property already exists
Description
Approval actions on Confluence pages can fail with an internal error. The log shows:
POST .../api/v2/pages/{pageId}/properties failed with HTTP status code 409 and error'Property with key [approvalPath] on page with id [{pageId}] already exists'
ApprovalConditionService.executeBatch reads the approvalPath content property, merges the approval changes into it, and writes it back. It creates the property with a POST if the read found nothing, and updates it with a PUT at version + 1 if it did. If another writer creates or changes the property between the read and the write, Confluence returns 409. Jira is not affected because its issue property PUT is an upsert.
decide locks the reference, but markOutdated (the page update webhook), archive and bulk archive do not, so they can race with it. A delete on a page with no property also creates one.
Impact: the exception is thrown inside the decide transaction, so the user's decision is rolled back and the dashboard shows an error.
Fix
-
ConfluenceApprovalAccess.setPropertyturns a 409 into aPropertyConflictException. This covers both "already exists" on create and a stale version on update. -
executeBatchretries the read, merge and write once, using the current property and its version. The existing definition ids are merged in, not overwritten with a value built from an empty state. -
A second consecutive conflict still propagates.
Testing notes:
Scenario A: Decision right after a page edit
-
On a Confluence page, start an approval with yourself as an approver.
-
Open the page editor in one tab and the approval (dashboard or page panel) in a second tab.
-
Publish the page in the first tab, then immediately click Approve or Reject in the second tab.
-
Repeat few times with fresh approvals.
Expected: no error appears in the UI, and the decision is saved every time (check after a refresh). The approval may be marked as outdated after the edit. That is normal.
Scenario B: Decision and archive on the same page
-
On one Confluence page, start two approvals from different definitions, with yourself as an approver of the first one.
-
Open the first approval in one tab and the dashboard list in a second tab.
-
Click Approve on the first approval in the first tab, and at the same time archive the second approval in the second tab.
-
Repeat a few times.
Expected: both actions succeed with no error. One is approved and the other is archived.
Scenario C: Page data is merged, not overwritten
-
Use a page with at least two approvals from different definitions. Get the page id from the page's "Page information" view or from the URL.
-
While logged in to Confluence, open <https://<site>>/wiki/api/v2/pages/<pageId>/properties?key=approvalPathQa in a browser and note the definition ids listed.
-
Approve, reject or archive one of the approvals.
-
Reload the URL from step 2.
Expected: every definition id from step 2 is still listed. Only the one you acted on has changed.