{"record":{"id":"b1fc9d71f41bff34","repo":"gastownhall/beads","slug":"worktree-removal-failure-is-absent-or-invalid","errorCode":null,"errorMessage":"worktree removal failure is absent or invalid","messagePattern":"worktree removal failure is absent or invalid","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/worktreeremove/policy.go","lineNumber":335,"sourceCode":"const (\n\tUnchangedFailure FailureKind = iota\n\tPartialFailure\n)\n\n// Failure is the pure classification returned after a mutation error.\ntype Failure struct {\n\tKind      FailureKind\n\tRemoveErr error\n}\n\n// ClassifyFailure distinguishes a safely unchanged target from partial or\n// indeterminate state. Presentation retains diagnostics at the command edge.\nfunc ClassifyFailure(plan Plan, facts FailureFacts, removeErr error) (Failure, error) {\n\tif !plan.valid() {\n\t\treturn Failure{}, fmt.Errorf(\"worktree removal approval is absent or invalid\")\n\t}\n\tif removeErr == nil {\n\t\treturn Failure{}, fmt.Errorf(\"worktree removal failure is absent or invalid\")\n\t}\n\tif facts.RevalidationResult == RevalidationPassed && facts.Registration == Present && facts.TargetPath == Present && revalidationValid(plan, facts.Revalidation) {\n\t\treturn Failure{Kind: UnchangedFailure, RemoveErr: removeErr}, nil\n\t}\n\treturn Failure{Kind: PartialFailure, RemoveErr: removeErr}, nil\n}\n","sourceCodeStart":317,"sourceCodeEnd":342,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/worktreeremove/policy.go#L317-L342","documentation":"ClassifyFailure exists to explain a removal error, so removeErr must be non-nil. If the caller invokes it after a removal that reported success (or with a nil error), there is nothing to classify and the function returns this error rather than fabricating an UnchangedFailure or PartialFailure result.","triggerScenarios":"Calling ClassifyFailure with removeErr == nil, typically when the caller's control flow reaches failure classification unconditionally instead of only when RemoveWorktree returned an error.","commonSituations":"Copy-pasted error handling where the nil-error success branch is missing; wrapper code that logs/classifies regardless of removal outcome; refactoring that inverted an if condition around the remove call.","solutions":["Only call ClassifyFailure when the removal function returned a non-nil error.","On removal success, take the success path instead of invoking classification.","If removal semantics changed, check err from Remove before deciding to classify."],"exampleFix":"// before\nclassification, err := ClassifyFailure(plan, ffacts, removeErr)\n\n// after\nif removeErr != nil {\n\tclassification, err = ClassifyFailure(plan, ffacts, removeErr)\n} else {\n\t// removal succeeded — success path\n}","handlingStrategy":"validation","validationCode":"if removeErr == nil {\n\t// success path — do not call ClassifyFailure\n\treturn nil\n}\nclassification, err := ClassifyFailure(plan, ffacts, removeErr)","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Call ClassifyFailure only inside the removal-error branch.","Keep success and failure paths visibly separate in the removal flow.","Avoid wrappers that classify unconditionally."],"tags":["worktree","git","nil-error","failure-classification"],"backgroundTag":"missing-error-argument","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}