{"record":{"id":"e548b077654b2822","repo":"wavetermdev/waveterm","slug":"error-deleting-block-w-e548b0","errorCode":null,"errorMessage":"error deleting block: %w","messagePattern":"error deleting block: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/wcore/block.go","lineNumber":175,"sourceCode":"func DeleteBlock(ctx context.Context, blockId string, recursive bool) error {\n\tblock, err := wstore.DBGet[*waveobj.Block](ctx, blockId)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error getting block: %w\", err)\n\t}\n\tif block == nil {\n\t\treturn nil\n\t}\n\tif len(block.SubBlockIds) > 0 {\n\t\tfor _, subBlockId := range block.SubBlockIds {\n\t\t\terr := DeleteBlock(ctx, subBlockId, recursive)\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"error deleting subblock %s: %w\", subBlockId, err)\n\t\t\t}\n\t\t}\n\t}\n\tparentBlockCount, err := deleteBlockObj(ctx, blockId)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error deleting block: %w\", err)\n\t}\n\tlog.Printf(\"DeleteBlock: parentBlockCount: %d\", parentBlockCount)\n\tparentORef := waveobj.ParseORefNoErr(block.ParentORef)\n\n\tif recursive && parentORef.OType == waveobj.OType_Tab && parentBlockCount == 0 {\n\t\t// if parent tab has no blocks, delete the tab\n\t\tlog.Printf(\"DeleteBlock: parent tab has no blocks, deleting tab %s\", parentORef.OID)\n\t\tparentWorkspaceId, err := wstore.DBFindWorkspaceForTabId(ctx, parentORef.OID)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"error finding workspace for tab to delete %s: %w\", parentORef.OID, err)\n\t\t}\n\t\tnewActiveTabId, err := DeleteTab(ctx, parentWorkspaceId, parentORef.OID, true)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"error deleting tab %s: %w\", parentORef.OID, err)\n\t\t}\n\t\tSendActiveTabUpdate(ctx, parentWorkspaceId, newActiveTabId)\n\t}\n\tsendBlockCloseEvent(blockId)","sourceCodeStart":157,"sourceCodeEnd":193,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/wcore/block.go#L157-L193","documentation":"After subblocks are cleared, DeleteBlock calls deleteBlockObj to remove the block row and compute the parent's remaining block count. If that transaction fails, the error is wrapped as \"error deleting block: %w\". This is the core record-deletion step for the block itself.","triggerScenarios":"deleteBlockObj returns an error: DBGet of the block fails, the block is unexpectedly nil, the block still has subblocks, or the parent lookup/update inside the transaction fails.","commonSituations":"Calling DeleteBlock on a parent without recursive=true while subblocks remain (though the wrapper usually surfaces the \"subblocks first\" message); transaction failure from store corruption or concurrent modification.","solutions":["Delete all subblocks first (pass recursive=true to DeleteBlock).","Read the wrapped cause to determine whether the DB read or the parent update failed.","Retry after fixing the store state; missing blocks short-circuit earlier, so retries are safe.","Check that no concurrent operation re-added subblocks between checks."],"exampleFix":"// before\nwclient.DeleteBlock(ctx, parentId, false) // subblocks remain -> fails\n// after\nwclient.DeleteBlock(ctx, parentId, true) // subblocks deleted before the parent","handlingStrategy":"try-catch","validationCode":"block, _ := wstore.DBGet[*waveobj.Block](ctx, blockId)\nready := block != nil && len(block.SubBlockIds) == 0","typeGuard":null,"tryCatchPattern":"if err := wcore.DeleteBlock(ctx, blockId, true); err != nil {\n    if strings.Contains(err.Error(), \"error deleting block\") {\n        log.Printf(\"core delete failed: %v\", err)\n    }\n    return err\n}","preventionTips":["Delete via the public DeleteBlock (recursive), not deleteBlockObj directly.","Ensure subblocks are cleared before any non-recursive delete.","Monitor wrapped causes for transaction/store health issues."],"tags":["wave-terminal","block-deletion","transaction","wrapped-error"],"backgroundTag":"cascade-delete-failed","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}