{"record":{"id":"05cd4767e5c1f9b4","repo":"gastownhall/beads","slug":"cannot-modify-hooked-issue-s-use-force-to-over","errorCode":null,"errorMessage":"cannot modify hooked issue %s (use --force to override)","messagePattern":"cannot modify hooked issue (.+?) \\(use --force to override\\)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"internal/validation/issue.go","lineNumber":244,"sourceCode":"\treturn func(id string, issue *types.Issue) error {\n\t\tif issue == nil {\n\t\t\treturn nil\n\t\t}\n\t\tif issue.Status == types.StatusClosed {\n\t\t\treturn fmt.Errorf(\"issue %s is already closed\", id)\n\t\t}\n\t\treturn nil\n\t}\n}\n\n// NotHooked validates that an issue is not in hooked status.\nfunc NotHooked(force bool) IssueValidator {\n\treturn func(id string, issue *types.Issue) error {\n\t\tif issue == nil {\n\t\t\treturn nil\n\t\t}\n\t\tif !force && issue.Status == types.StatusHooked {\n\t\t\treturn fmt.Errorf(\"cannot modify hooked issue %s (use --force to override)\", id)\n\t\t}\n\t\treturn nil\n\t}\n}\n\n// HasStatus validates that an issue has one of the allowed statuses.\nfunc HasStatus(allowed ...types.Status) IssueValidator {\n\treturn func(id string, issue *types.Issue) error {\n\t\tif issue == nil {\n\t\t\treturn nil\n\t\t}\n\t\tfor _, status := range allowed {\n\t\t\tif issue.Status == status {\n\t\t\t\treturn nil\n\t\t\t}\n\t\t}\n\t\treturn fmt.Errorf(\"issue %s has status %s, expected one of: %v\", id, issue.Status, allowed)\n\t}","sourceCodeStart":226,"sourceCodeEnd":262,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/validation/issue.go#L226-L262","documentation":"This error comes from the NotHooked validator, which protects issues in the special 'hooked' status from accidental modification. Hooked issues are typically locked by an external process or dependency, so the library requires explicit opt-in via a force flag. The message tells the user exactly which issue is protected and how to override.","triggerScenarios":"Calling an update/mutation that runs NotHooked on an issue with issue.Status == types.StatusHooked while the force parameter is false. Passing force=true bypasses the check; a nil issue passes.","commonSituations":"An agent or sync process has marked an issue as hooked (in-progress claim) and another process tries to edit it; a developer manually edits an issue currently claimed by a running workflow; automated scripts colliding with a long-running operation on the same issue.","solutions":["Wait for the owning process to finish and release the hook, then retry the operation","Confirm no other process is actively working on the issue, then re-run with the force flag (e.g. bd update <id> --force ...)","Coordinate via the hook owner: close or unhook the issue properly instead of force-overriding","Add a pre-check of issue.Status != StatusHooked in automation before attempting edits"],"exampleFix":"// before\nbd.Update(id, changes) // blocked because issue is hooked\n// after\nissue := getIssue(id)\nif issue.Status == types.StatusHooked {\n    // verify no active owner, then\n    bd.UpdateForce(id, changes) // or wait and retry without force\n}","handlingStrategy":"validation","validationCode":"func canModify(issue *types.Issue, force bool) bool {\n    return issue != nil && (force || issue.Status != types.StatusHooked)\n}","typeGuard":"func isHooked(issue *types.Issue) bool {\n    return issue != nil && issue.Status == types.StatusHooked\n}","tryCatchPattern":"if err := updateIssue(id, changes); err != nil {\n    if strings.Contains(err.Error(), \"cannot modify hooked issue\") {\n        return errHookedNeedsForce // surface to user with --force hint\n    }\n    return err\n}","preventionTips":["Check for hooked status before editing issues in automation","Implement hook-aware retry with backoff in multi-agent workflows","Only use --force after verifying no active owner of the hook","Log and alert on force-overrides for auditability"],"tags":["validation","concurrency","locking"],"backgroundTag":"issue-locked-by-hook","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}