{"record":{"id":"f90a5b65988fee99","repo":"gastownhall/beads","slug":"delete-drop-sync-plane-edges-into-deleted-wisps","errorCode":null,"errorMessage":"delete: drop sync-plane edges into deleted wisps: %w","messagePattern":"delete: drop sync-plane edges into deleted wisps: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/domain/issue_delete.go","lineNumber":181,"sourceCode":"\t\treturn result, fmt.Errorf(\"delete: affected by deletion: %w\", err)\n\t}\n\n\tif _, err := u.depRepo.DeleteAllForIDs(ctx, regularIDs, DepInsertOpts{}); err != nil {\n\t\treturn result, fmt.Errorf(\"delete: drop deps: %w\", err)\n\t}\n\tif _, err := u.depRepo.DeleteAllForIDs(ctx, wispIDs, DepInsertOpts{UseWispsTable: true}); err != nil {\n\t\treturn result, fmt.Errorf(\"delete: drop wisp deps: %w\", err)\n\t}\n\t// The SYNC-PLANE edges pointing at a deleted wisp, which are not the same\n\t// rows as the line above and are not reached by a foreign key: there is no\n\t// FK from dependencies to wisps, so `dependencies.depends_on_wisp_id` rows\n\t// survive their target unless they are deleted explicitly. Without this a\n\t// forced delete of a wisp left its durable dependent holding an edge into\n\t// a row that no longer exists — dangling, not orphaned, which is not what\n\t// issueops.DeleteRequest.Force promises. The store body has always done\n\t// this (issueops.deleteIssueRowInTx -> DeleteWispFromDependenciesInTx).\n\tif _, err := u.depRepo.DeleteAllForIDs(ctx, wispIDs, DepInsertOpts{}); err != nil {\n\t\treturn result, fmt.Errorf(\"delete: drop sync-plane edges into deleted wisps: %w\", err)\n\t}\n\tif _, err := u.labelRepo.DeleteAllForIDs(ctx, regularIDs, LabelOpts{}); err != nil {\n\t\treturn result, fmt.Errorf(\"delete: drop labels: %w\", err)\n\t}\n\tif _, err := u.labelRepo.DeleteAllForIDs(ctx, wispIDs, LabelOpts{UseWispsTable: true}); err != nil {\n\t\treturn result, fmt.Errorf(\"delete: drop wisp labels: %w\", err)\n\t}\n\tif _, err := u.eventsRepo.DeleteAllForIDs(ctx, regularIDs, RecordEventOpts{}); err != nil {\n\t\treturn result, fmt.Errorf(\"delete: drop events: %w\", err)\n\t}\n\tif _, err := u.eventsRepo.DeleteAllForIDs(ctx, wispIDs, RecordEventOpts{UseWispsTable: true}); err != nil {\n\t\treturn result, fmt.Errorf(\"delete: drop wisp events: %w\", err)\n\t}\n\n\tissuesDeleted, err := u.issueRepo.DeleteByIDs(ctx, regularIDs, IssueTableOpts{})\n\tif err != nil {\n\t\treturn result, fmt.Errorf(\"delete: drop issue rows: %w\", err)\n\t}","sourceCodeStart":163,"sourceCodeEnd":199,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/domain/issue_delete.go#L163-L199","documentation":"Wraps failure of the explicit sync-plane cleanup: dependencies.depends_on_wisp_id rows pointing at deleted wisps have no foreign key, so they are deleted separately (regular-table DeleteAllForIDs with the wisp IDs). If this DELETE fails, dangling edges would remain, violating Force-delete semantics, so the operation aborts with this error.","triggerScenarios":"A forced delete involving wisps where the regular dependencies table cannot be written (missing table, lock contention, driver error, cancelled context) during the third depRepo.DeleteAllForIDs call.","commonSituations":"Schema drift where the sync-plane dependencies table is absent; DB under heavy write load causing lock wait timeouts; connection dropped mid-batch on large wisp deletions.","solutions":["Check the regular dependencies table exists and is writable in the embedded DB.","Retry the delete — transactional cleanup prevents partial dangling edges.","Inspect the wrapped cause for lock/permission errors and resolve them.","Avoid deleting very large wisp sets in one call; chunk the IDs."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"if err := ctx.Err(); err != nil { return err }\nexists, err := tableExists(ctx, \"dependencies\"); if err != nil || !exists { return fmt.Errorf(\"sync-plane dependencies table missing\") }","typeGuard":"var dbe *storage.DBError\nif errors.As(err, &dbe) { /* inspect driver cause */ }","tryCatchPattern":"if err := store.DeleteWisps(ctx, ids, opts); err != nil {\n    if strings.Contains(err.Error(), \"drop sync-plane edges\") {\n        // retry; do not assume deletions are partial — op is transactional\n    }\n}","preventionTips":["Ensure schema migrations are applied before deleting wisps.","Keep context deadlines generous for forced deletes with dependents.","Monitor for lock wait timeouts under concurrent load.","Batch wisp deletions into modest ID sets."],"tags":["storage","database","wisps","dependencies","data-integrity"],"backgroundTag":"dependency-delete-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}