{"record":{"id":"2fd5f51e906d817d","repo":"gastownhall/beads","slug":"issue-s-has-status-s-expected-one-of-v","errorCode":null,"errorMessage":"issue %s has status %s, expected one of: %v","messagePattern":"issue (.+?) has status (.+?), expected one of: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/validation/issue.go","lineNumber":261,"sourceCode":"\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}\n}\n\n// HasType validates that an issue has one of the allowed types.\nfunc HasType(allowed ...types.IssueType) 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 _, t := range allowed {\n\t\t\tif issue.IssueType == t {\n\t\t\t\treturn nil\n\t\t\t}\n\t\t}\n\t\treturn fmt.Errorf(\"issue %s has type %s, expected one of: %v\", id, issue.IssueType, allowed)\n\t}\n}\n","sourceCodeStart":243,"sourceCodeEnd":279,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/validation/issue.go#L243-L279","documentation":"This error is produced by the HasStatus validator when an operation requires the issue to be in one of a specific set of allowed statuses, but the issue's actual Status matches none of them. It reports the current status and the full list of allowed values so the caller can see the mismatch immediately. The library uses it to enforce preconditions like 'issue must be open to be assigned'.","triggerScenarios":"Any API call configured with HasStatus(allowed...) on an issue whose issue.Status is not in the allowed slice (e.g. updating an issue expected to be 'open' while it is 'in_progress' or 'closed').","commonSituations":"Workflow automations assuming a status that a prior step already changed; stale cached issue data where the status moved on; status naming drift after library upgrades changing the allowed set; bulk scripts applying operations to issues in mixed states.","solutions":["Fetch the issue and check its Status against the expected set before the call, transitioning it if needed","Broaden or correct the allowed status list passed to HasStatus if the requirement is too strict","Refresh/re-fetch the issue if your local copy may be stale","Fix upstream workflow logic that leaves issues in unexpected statuses"],"exampleFix":"// before\nValidate(id, issue, HasStatus(types.StatusOpen)) // fails if in_progress\n// after\nValidate(id, issue, HasStatus(types.StatusOpen, types.StatusInProgress))","handlingStrategy":"validation","validationCode":"func hasAllowedStatus(issue *types.Issue, allowed ...types.Status) bool {\n    if issue == nil {\n        return false\n    }\n    for _, s := range allowed {\n        if issue.Status == s {\n            return true\n        }\n    }\n    return false\n}","typeGuard":"func statusIn(issue *types.Issue, allowed ...types.Status) bool {\n    return issue != nil && slices.Contains(allowed, issue.Status)\n}","tryCatchPattern":"if err := validate(id, issue); err != nil {\n    if strings.Contains(err.Error(), \"expected one of\") {\n        issue = refresh(id) // re-fetch and re-check before failing\n    }\n    return err\n}","preventionTips":["Re-fetch issues before status-sensitive operations instead of using cached data","Model status transitions explicitly so workflows never assume a stale status","Keep the allowed-status lists in sync with the library's types after upgrades","Add pre-flight status checks in bulk scripts with clear skip/report behavior"],"tags":["validation","status","precondition"],"backgroundTag":"invalid-issue-status","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}