{"record":{"id":"d1f0fdf266d55a94","repo":"gastownhall/beads","slug":"errdependentsoutsiderequest","errorCode":"ErrDependentsOutsideRequest","errorMessage":"dependents outside deletion set","messagePattern":"dependents outside deletion set","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"issueops/deleter.go","lineNumber":203,"sourceCode":"\t// It is populated exactly when the request carried Force without Cascade —\n\t// the only mode in which orphaning is possible — and is empty otherwise.\n\t// It is also carried on the DependentsOutsideRequestError the unforced\n\t// mode returns, so the same fact reaches a caller whichever answer it got.\n\t//\n\t// It is DIRECT dependents only. A row two edges away loses no edge and is\n\t// not orphaned by this deletion; it is merely blocked by something that is\n\t// now blocked by nothing.\n\tOrphaned []string\n}\n\n// ErrDependentsOutsideRequest classifies the unforced refusal: a named row has\n// a dependent the request did not name, and neither Cascade nor Force said\n// what to do about it.\n//\n// It lives beside the role rather than in errors.go because it is meaningless\n// without DeleteRequest.Cascade and DeleteRequest.Force to explain it, and\n// errors.go is the file every parallel role slice touches.\nvar ErrDependentsOutsideRequest = errors.New(\"dependents outside deletion set\")\n\n// DependentsOutsideRequestError reports WHICH row was blocked and by WHAT, so\n// a caller can name them without parsing the message. It wraps the sentinel\n// rather than replacing it.\n//\n// It names ONE blocked row — the first the implementation reached — rather\n// than every blocked row in the request. That is deliberate and matches the\n// only answer a caller can act on: the request is refused whole, so the second\n// blocked row changes nothing about what to do next, and enumerating all of\n// them would cost a full scan on the path that deletes nothing.\ntype DependentsOutsideRequestError struct {\n\t// IssueID is the named row that has dependents outside the request.\n\tIssueID string\n\t// Dependents are that row's direct dependents that the request did not\n\t// name, in ascending id order.\n\tDependents []string\n}\n","sourceCodeStart":185,"sourceCodeEnd":221,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/issueops/deleter.go#L185-L221","documentation":"ErrDependentsOutsideRequest is returned by the deleter when a delete request would remove an issue that has dependents the request did not name, and neither Cascade nor Force said what to do. DependentsOutsideRequestError wraps the sentinel and reports which row was blocked and by what, naming one blocked row (the first the implementation reached). It lives in issueops/deleter.go because it is meaningless without DeleteRequest.Cascade/Force.","triggerScenarios":"Calling the deleter (RunDeleter paths, failDeleteErr) with a DeleteRequest that omits Cascade and Force while the target issue has dependents not included in the request; deleting a parent whose children were not named.","commonSituations":"Deleting a parent issue without realizing it has open children; batch cleanup scripts that delete leaves' parents; refactors that re-parent issues leaving stale dependents.","solutions":["Inspect DependentsOutsideRequestError to see the blocked row and its dependents, then include those dependents in the request or delete them first.","Set DeleteRequest.Cascade = true to delete dependents along with the target.","Set DeleteRequest.Force = true to deliberately ignore unmanaged dependents.","Query dependencies before deleting and build a complete deletion set."],"exampleFix":"// before\nerr := deleter.Delete(ctx, types.DeleteRequest{Issues: []string{\"bd-5\"}}) // blocked\n\n// after\nerr := deleter.Delete(ctx, types.DeleteRequest{Issues: []string{\"bd-5\"}, Cascade: true})\n// or inspect err.(*issueops.DependentsOutsideRequestError) to name the blockers","handlingStrategy":"validation","validationCode":"deps, _ := store.GetDependents(ctx, targetID)\nif len(deps) > 0 && !req.Cascade && !req.Force {\n    // expand request or set Cascade/Force before deleting\n}","typeGuard":"var d *issueops.DependentsOutsideRequestError\nif errors.As(err, &d) {\n    // d names the blocked row and its dependents\n}","tryCatchPattern":"if errors.Is(err, issueops.ErrDependentsOutsideRequest) {\n    var d *issueops.DependentsOutsideRequestError\n    errors.As(err, &d) // name the row/dependents to the user\n}","preventionTips":["Query dependents before building a DeleteRequest.","Decide explicitly between Cascade and Force in automation.","Never default to Force in shared workspaces."],"tags":["deletion","dependencies","safety-guard"],"backgroundTag":"blocked-by-dependents","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}