{"record":{"id":"3c5098fdc44c4a85","repo":"vxcontrol/pentagi","slug":"failed-to-delete-source-directory-q-w","errorCode":null,"errorMessage":"failed to delete source directory %q: %w","messagePattern":"failed to delete source directory %q: %w","errorType":"http","errorClass":null,"httpStatus":500,"severity":"error","filePath":"backend/pkg/server/services/resources.go","lineNumber":1116,"sourceCode":"\t\t\t}\n\t\t}\n\n\t\tupdated, err := updateMovedResource(tx, entry, newPath, now)\n\t\tif err != nil {\n\t\t\treturn result, err\n\t\t}\n\t\tresult.Updated = append(result.Updated, convertResource(updated))\n\t}\n\n\tfor _, dir := range sourceDirsToDelete {\n\t\tif err := tx.Delete(&dir).Error; err != nil {\n\t\t\treturn result, fmt.Errorf(\"failed to delete merged source directory %q: %w\", dir.Path, err)\n\t\t}\n\t\tresult.DeletedAfter = append(result.DeletedAfter, convertResource(dir))\n\t}\n\tif sourceRoot != nil {\n\t\tif err := tx.Delete(sourceRoot).Error; err != nil {\n\t\t\treturn result, fmt.Errorf(\"failed to delete source directory %q: %w\", sourceRoot.Path, err)\n\t\t}\n\t\tresult.DeletedAfter = append(result.DeletedAfter, convertResource(*sourceRoot))\n\t}\n\n\treturn result, nil\n}\n\nfunc listResourceTree(tx *gorm.DB, uid uint64, rootPath string) ([]models.UserResource, error) {\n\tescapedRoot := resources.EscapeLike(rootPath)\n\tvar entries []models.UserResource\n\tif err := tx.Where(\n\t\t\"user_id = ? AND (path = ? OR path LIKE ?)\",\n\t\tuid, rootPath, escapedRoot+\"/%\",\n\t).Order(\"path ASC\").Find(&entries).Error; err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to list source directory: %w\", err)\n\t}\n\treturn entries, nil\n}","sourceCodeStart":1098,"sourceCodeEnd":1134,"githubUrl":"https://github.com/vxcontrol/pentagi/blob/ea665308baaff015b226f308438a68d929d0f29b/backend/pkg/server/services/resources.go#L1098-L1134","documentation":"The final step of a directory merge removes the source root directory row itself. If that delete fails the error wraps the DB error with the source path in the message and rolls back the whole merge, keeping source and destination consistent.","triggerScenarios":"All child entries were merged/deleted but tx.Delete(sourceRoot) fails — typically a remaining FK reference to the root directory row (e.g. logs, tool results pointing at the path), row locks, or connection loss.","commonSituations":"Implicit references to the source directory stored outside user_resources without cascade; long-running transactions holding locks on the row; DB failover mid-merge.","solutions":["Find what still references the source directory row and clean it up or add cascade","Inspect the wrapped driver error for the specific constraint","Retry the merge after contention/transient DB issues are resolved"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"err := svc.MoveResource(ctx, uid, srcDir, dstDir, true)\nif err != nil && strings.Contains(err.Error(), \"failed to delete source directory\") {\n    // find lingering FK references to the source row via the wrapped error\n}","preventionTips":["Audit tables referencing user_resources for cascade behavior","Clean up path-keyed references in logs/results tables","Retry with backoff on transient DB failures"],"tags":["database","gorm","delete","merge"],"backgroundTag":"database-delete-failed","analyzedSha":"ea665308baaff015b226f308438a68d929d0f29b","analyzedAt":"2026-09-01T14:16:31.421Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}