Repository: umbraco/Umbraco-CMS

Issue #15476: Saving a Content Node with a Form chosen in a Block List results in a duplicate key exception for IX_umbracoRelation_parentChildType
Created: 2023-12-18T22:43:32Z
Which Umbraco version are you using? (Please write the exact version, example: 10.1.0)
12.3.5, and Umbraco Forms 12.2.0
Bug summary
We have a Block List block that allows us to pick an Umbraco Form.  When we save the content node for the first time it creates a Relationship between the Content Node and the Form.
If we subsequently attempt to save the page, it tries to add the relationship a second time, resulting in a duplicate key row.
Specifics
Cannot insert duplicate key row in object 'dbo.umbracoRelation' with unique index 'IX_umbracoRelation_parentChildType'. The duplicate key value is (1497, 1624, 6). The statement has been terminated.
Exception Details
Microsoft.Data.SqlClient.SqlException, Microsoft.Data.SqlClient, Version=5.0.0.0, Culture=neutral, PublicKeyToken=23ec7fc2d6eaa4a5: Cannot insert duplicate key row in object 'dbo.umbracoRelation' with unique index 'IX_umbracoRelation_parentChildType'. The duplicate key value is (1497, 1624, 6). The statement has been terminated.

Stacktrace
at Microsoft.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
   at Microsoft.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)
   at Microsoft.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj)
   at Microsoft.Data.SqlClient.SqlBulkCopy.RunParser(BulkCopySimpleResultSet bulkCopyHandler)
   at Microsoft.Data.SqlClient.SqlBulkCopy.CopyBatchesAsyncContinuedOnSuccess(BulkCopySimpleResultSet internalResults, String updateBulkCommandText, CancellationToken cts, TaskCompletionSource`1 source)
   at Microsoft.Data.SqlClient.SqlBulkCopy.CopyBatchesAsyncContinued(BulkCopySimpleResultSet internalResults, String updateBulkCommandText, CancellationToken cts, TaskCompletionSource`1 source)
   at Microsoft.Data.SqlClient.SqlBulkCopy.CopyBatchesAsync(BulkCopySimpleResultSet internalResults, String updateBulkCommandText, CancellationToken cts, TaskCompletionSource`1 source)
   at Microsoft.Data.SqlClient.SqlBulkCopy.WriteToServerInternalRestContinuedAsync(BulkCopySimpleResultSet internalResults, CancellationToken cts, TaskCompletionSource`1 source)
   at Microsoft.Data.SqlClient.SqlBulkCopy.WriteToServerInternalRestAsync(CancellationToken cts, TaskCompletionSource`1 source)
   at Microsoft.Data.SqlClient.SqlBulkCopy.WriteToServerInternalAsync(CancellationToken ctoken)
   at Microsoft.Data.SqlClient.SqlBulkCopy.WriteRowSourceToServerAsync(Int32 columnCount, CancellationToken ctoken)
   at Microsoft.Data.SqlClient.SqlBulkCopy.WriteToServer(DataTable table, DataRowState rowState)
   at Microsoft.Data.SqlClient.SqlBulkCopy.WriteToServer(DataTable table)
   at NPoco.SqlServer.SqlBulkCopyHelper.BulkInsert[T](IDatabase db, IEnumerable`1 list, SqlBulkCopyOptions sqlBulkCopyOptions, InsertBulkOptions insertBulkOptions)
   at NPoco.SqlServer.SqlBulkCopyHelper.BulkInsert[T](IDatabase db, IEnumerable`1 list, InsertBulkOptions insertBulkOptions)
   at NPoco.DatabaseTypes.SqlServerDatabaseType.InsertBulk[T](IDatabase db, IEnumerable`1 pocos, InsertBulkOptions options)
   at NPoco.Database.InsertBulk[T](IEnumerable`1 pocos, InsertBulkOptions options)
   at Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement.RelationRepository.SaveBulk(IEnumerable`1 relations)
   at Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement.ContentRepositoryBase`3.PersistRelations(TEntity entity)
   at Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement.DocumentRepository.PersistUpdatedItem(IContent entity)
   at Umbraco.Cms.Core.Cache.DefaultRepositoryCachePolicy`2.Update(TEntity entity, Action`1 persistUpdated)
   at Umbraco.Cms.Core.Services.ContentService.<>c__DisplayClass66_0.<CommitDocumentChangesInternal>g__SaveDocument|2(IContent c)
   at Umbraco.Cms.Core.Services.ContentService.CommitDocumentChangesInternal(ICoreScope scope, IContent content, EventMessages eventMessages, IReadOnlyCollection`1 allLangs, IDictionary`2 notificationState, Int32 userId, Boolean branchOne, Boolean branchRoot)
   at Umbraco.Cms.Core.Services.ContentService.SaveAndPublish(IContent content, String culture, Int32 userId)
   at Umbraco.Cms.Web.BackOffice.Controllers.ContentController.PublishInternal(ContentItemSave contentItem, String defaultCulture, String cultureForInvariantErrors, Boolean& wasCancelled, String[]& successfulCultures)
   at Umbraco.Cms.Web.BackOffice.Controllers.ContentController.PostSaveInternal[TVariant](ContentItemSave contentItem, Func`3 saveMethod, Func`2 mapToDisplay)
   at Umbraco.Cms.Web.BackOffice.Controllers.ContentController.PostSave(ContentItemSave contentItem)
   at lambda_method4033(Closure, Object)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.AwaitableObjectResultExecutor.Execute(ActionContext actionContext, IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeActionMethodAsync>g__Awaited|12_0(ControllerActionInvoker invoker, ValueTask`1 actionResultValueTask)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeNextActionFilterAsync>g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync()
--- End of stack trace from previous location ---
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextExceptionFilterAsync>g__Awaited|26_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)

Steps to reproduce

Add a Block List Element that has an Umbraco Form picker in it
Add a Document Type with a Block List containing the configured Block List Element
Add a new content node based on the Document Type, choose a form in the block list and save
Attempt to save a second time - the exception should be thrown.

Expected result / actual result
Re-saving a content node with a form referenced in a block list element should not attempt to re-create the relationship between the form and the content node.

Duplicate issue #15491: Umbraco Forms: Duplicate key row in object 'dbo.umbracoRelation' with unique index 'IX_umbracoRelation_parentChildType'
Created: 2023-12-20T15:07:14Z
Which Umbraco version are you using? (Please write the exact version, example: 10.1.0)
12.3.6
Bug summary
Umbraco Forms form added to a node (in my case added via an "Insert Form" macro within an RTE), it adds a row to the dbo.umbracoRelation table on publish. However, when you try to publish a 2nd time, it is throwing this error:
. The only way to publish is to manually delete the row matching the given key from the error message.
I thought this would potentially be fixed by today's patch, the "GetRelations" caching fix - however, after just updating, this issue persists.
Note: the same goes for unpublishing/deleting a node that contains an existing form - the same error will display and prevent the action from completing.
Specifics
Server error: Contact administrator, see log for full details.
Cannot insert duplicate key row in object 'dbo.umbracoRelation' with unique index 'IX_umbracoRelation_parentChildType'. The duplicate key value is (3094, 3378, 6). The statement has been terminated.
Umbraco Forms: 12.2.1 (noticed also yesterday at 12.2.0)
Umbraco: 12.3.6 (noticed also yesterday at 12.3.5)
Microsoft.Data.SqlClient.SqlException (0x80131904): Cannot insert duplicate key row in object 'dbo.umbracoRelation' with unique index 'IX_umbracoRelation_parentChildType'. The duplicate key value is (2579, 3404, 6). The statement has been terminated. at Microsoft.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action1 wrapCloseInAction)
at Microsoft.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
at Microsoft.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)
at Microsoft.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj)
at Microsoft.Data.SqlClient.SqlBulkCopy.RunParser(BulkCopySimpleResultSet bulkCopyHandler)
at Microsoft.Data.SqlClient.SqlBulkCopy.CopyBatchesAsyncContinuedOnSuccess(BulkCopySimpleResultSet internalResults, String updateBulkCommandText, CancellationToken cts, TaskCompletionSource1 source) at Microsoft.Data.SqlClient.SqlBulkCopy.CopyBatchesAsyncContinued(BulkCopySimpleResultSet internalResults, String updateBulkCommandText, CancellationToken cts, TaskCompletionSource1 source)
at Microsoft.Data.SqlClient.SqlBulkCopy.CopyBatchesAsync(BulkCopySimpleResultSet internalResults, String updateBulkCommandText, CancellationToken cts, TaskCompletionSource1 source) at Microsoft.Data.SqlClient.SqlBulkCopy.WriteToServerInternalRestContinuedAsync(BulkCopySimpleResultSet internalResults, CancellationToken cts, TaskCompletionSource1 source)
at Microsoft.Data.SqlClient.SqlBulkCopy.WriteToServerInternalRestAsync(CancellationToken cts, TaskCompletionSource1 source) at Microsoft.Data.SqlClient.SqlBulkCopy.WriteToServerInternalAsync(CancellationToken ctoken) at Microsoft.Data.SqlClient.SqlBulkCopy.WriteRowSourceToServerAsync(Int32 columnCount, CancellationToken ctoken) at Microsoft.Data.SqlClient.SqlBulkCopy.WriteToServer(DataTable table, DataRowState rowState) at Microsoft.Data.SqlClient.SqlBulkCopy.WriteToServer(DataTable table) at NPoco.SqlServer.SqlBulkCopyHelper.BulkInsert[T](IDatabase db, IEnumerable1 list, SqlBulkCopyOptions sqlBulkCopyOptions, InsertBulkOptions insertBulkOptions)
at NPoco.SqlServer.SqlBulkCopyHelper.BulkInsert[T](IDatabase db, IEnumerable1 list, InsertBulkOptions insertBulkOptions) at NPoco.DatabaseTypes.SqlServerDatabaseType.InsertBulk[T](IDatabase db, IEnumerable1 pocos, InsertBulkOptions options)
at NPoco.Database.InsertBulk[T](IEnumerable1 pocos, InsertBulkOptions options) at Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement.RelationRepository.SaveBulk(IEnumerable1 relations)
at Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement.ContentRepositoryBase3.PersistRelations(TEntity entity) at Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement.DocumentRepository.PersistUpdatedItem(IContent entity) at Umbraco.Cms.Core.Cache.DefaultRepositoryCachePolicy2.Update(TEntity entity, Action1 persistUpdated) at Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement.EntityRepositoryBase2.Save(TEntity entity)
at Umbraco.Cms.Core.Services.ContentService.<>c__DisplayClass66_0.g__SaveDocument|2(IContent c)
at Umbraco.Cms.Core.Services.ContentService.CommitDocumentChangesInternal(ICoreScope scope, IContent content, EventMessages eventMessages, IReadOnlyCollection1 allLangs, IDictionary2 notificationState, Int32 userId, Boolean branchOne, Boolean branchRoot)
at Umbraco.Cms.Core.Services.ContentService.SaveAndPublish(IContent content, String culture, Int32 userId)
at Umbraco.Cms.Web.BackOffice.Controllers.ContentController.PublishInternal(ContentItemSave contentItem, String defaultCulture, String cultureForInvariantErrors, Boolean& wasCancelled, String[]& successfulCultures)
at Umbraco.Cms.Web.BackOffice.Controllers.ContentController.PostSaveInternal[TVariant](ContentItemSave contentItem, Func3 saveMethod, Func2 mapToDisplay)
ClientConnectionId:c5f5ed48-9c18-4b63-861c-3bf0bddd48db
Error Number:2601,State:1,Class:14
ClientConnectionId before routing:53414966-9d07-47f4-a3bc-ae0c4194fdae
Routing Destination:b33f1f523de2.tr31953.eastus1-a.worker.database.windows.net,11057`
Steps to reproduce
Create an umbraco form
Add the form to a page (potentially via an RTE "Insert Form" macro)
Publish the page. (should be successful the first time)
Publish the page again.  (should fail here, given the dbo.umbracoRelation table key already exists)
Expected result / actual result
Page should publish/unpublish/delete successfully. Expected that the dbo.umbracoRelations row would be cleared (or incremented, or checked somehow) as to no longer conflict and cause a duplicate unique index error.

Closing comment (2023-12-20T16:56:43Z): This issue seems to be a duplicate of #15476. I will go ahead and close this issue. 😄