-
Type:
Bug
-
Resolution: Fixed
-
Priority:
Medium
-
Affects Version/s: 9.2.7, 10.2.14, 9.2.22
-
Component/s: Content - Blueprints / Templates, Content - Labels
-
1
-
Severity 3 - Minor
-
RtB - Service ops & Tech entropy
Issue Summary
Adding or removing labels on page templates fails with a 500 Internal Server Error when at least one content management incremental sync subscription (containing the 'PAGE_EVENT' type) is active.
This affects both creating new templates with labels and editing existing templates to add/remove labels. Labels on regular pages and blog posts are unaffected.
Steps to Reproduce
Path 1 — Creating a new template
1. Create a subscription (see section below)
2. Create a page template and add labels to it
3. Save the template
4. At this stage, it will look like it has succeeded, but in reality will silently fail. The new template will be absent from the list entirely.
Path 2 — Updating an existing template
1. Create a subscription (see section below)
2. Create a page template without any labels, save it.
3. Edit the page template and try to add a label to it.
4. This will trigger the error as long as at least one subscription exists.
Create a subscription
The crucial part is setting up an incremental sync subscription. We can do this easily enough with a few REST API calls. These examples are using basic auth because it is quick and easy, but any valid authentication method should work. Crucially, the subscription must contain PAGE_EVENT as a type, as this includes page template updates.
curl -u $USER:$PASSWORD -X POST \ "$CONFLUENCE_BASE_URL/rest/internal/sync/latest/contentmanagement/event/subscription" \ -H "Content-Type: application/json" \ -d '{"types": ["PAGE_EVENT"]}'
It may also be useful to know the endpoints to list and delete subscriptions to compare before and after:
List subscriptions
curl -u $USER:$PASSWORD \
"$CONFLUENCE_BASE_URL/rest/internal/sync/latest/contentmanagement/event/subscriptions"
Delete subscription by ID
You can get the ID in the response from the original create request, or by using the list endpoint (above), OR by inspecting the `INCREMENTAL_SYNC_SUBSCRIPTION` database table.
curl -u $USER:$PASSWORD -X DELETE \
"$CONFLUENCE_BASE_URL/rest/internal/sync/latest/contentmanagement/event/subscription/$SUBSCRIPTION_ID"
Expected Results
Path 1 — Creating a new template
The new template is saved and includes the labels.
Path 2— Updating an existing template
The template is updated to include the new labels.
Actual Results
Path 1 — Creating a new template
The creation of the template silently fails. No new template will appear in the list and nothing will be be saved.
Path 2 — Updating an existing template
Updating the template will visibly fail and provide a traceID for log analysis.

In both cases, an exception is thrown in the logs and the transaction is rolled back.
ERROR [http-nio-8080-exec-3] [service.incrementalsync.AbstractRecorder] handleEvent Failed to handle event com.atlassian.confluence.event.events.label.LabelAddEvent[source=test] for user management incremental syncjava.lang.ClassCastException: class com.atlassian.confluence.pages.templates.PageTemplate cannot be cast to class com.atlassian.confluence.core.ContentEntityObject (com.atlassian.confluence.pages.templates.PageTemplate and com.atlassian.confluence.core.ContentEntityObject are in unnamed module of loader org.apache.catalina.loader.ParallelWebappClassLoader @7008055) at com.atlassian.confluence.internal.api.impl.service.incrementalsync.contentmanagement.commands.AbstractLabelCommand.processEvent(AbstractLabelCommand.java:52) at com.atlassian.confluence.internal.api.impl.service.incrementalsync.contentmanagement.commands.AbstractLabelCommand.processEvent(AbstractLabelCommand.java:35) at com.atlassian.confluence.internal.api.impl.service.incrementalsync.contentmanagement.ContentManagementRecorder.lambda$executeCommand$0(ContentManagementRecorder.java:262) at com.atlassian.confluence.internal.api.impl.service.incrementalsync.contentmanagement.ContentManagementIncrementalSyncServiceImpl.lambda$handleEventForSubscription$3(ContentManagementIncrementalSyncServiceImpl.java:162) at com.atlassian.confluence.internal.api.impl.service.incrementalsync.contentmanagement.ContentManagementIncrementalSyncServiceImpl.handleEventForSubscription(ContentManagementIncrementalSyncServiceImpl.java:156) at com.atlassian.confluence.internal.api.impl.service.incrementalsync.contentmanagement.ContentManagementRecorder.executeCommand(ContentManagementRecorder.java:259) at com.atlassian.confluence.internal.api.impl.service.incrementalsync.AbstractRecorder.lambda$handleEvent$0(AbstractRecorder.java:33) at com.atlassian.confluence.internal.api.impl.service.incrementalsync.AbstractRecorder.lambda$executeWithTransaction$3(AbstractRecorder.java:50) at com.atlassian.confluence.internal.api.impl.service.incrementalsync.AbstractRecorder.handleEvent(AbstractRecorder.java:33) at com.atlassian.confluence.internal.api.impl.service.incrementalsync.contentmanagement.ContentManagementRecorder.onLabelAddEvent(ContentManagementRecorder.java:249) WARN [http-nio-8080-exec-3] [impl.hibernate.ConfluenceHibernateTransactionManager] doRollback Performing rollback. Transactions: ->[com.atlassian.confluence.labels.service.AddLabelsCommandImpl.execute]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT ERROR [http-nio-8080-exec-3] [api.model.ExceptionConverter] convertServiceException No status code found for exception, converting to internal server error.org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only at org.springframework.transaction.support.AbstractPlatformTransactionManager.processRollback(AbstractPlatformTransactionManager.java:938) at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:754) at com.atlassian.confluence.labels.DefaultLabelManager.addLabel(DefaultLabelManager.java:93) at com.atlassian.confluence.impl.labels.CachingLabelManager.addLabel(CachingLabelManager.java:109)
Workaround
Currently the only known workaround is to disable or remove the incremental sync subscription, which can be done with the API calls mentioned in Steps to Reproduce.
Admins can inspect the `INCREMENTAL_SYNC_SUBSCRIPTION` table in the database to understand their instance's subscriptions.
This can also be achieved by changing subscription states to INACTIVE in the same table.
However while disabled, all content change events for this subscription will be silently dropped, meaning a full re-sync is required to realign the consumer's state.