{"record":{"id":"a27e53866b22ef4f","repo":"gastownhall/beads","slug":"issue-s-has-type-s-expected-one-of-v","errorCode":null,"errorMessage":"issue %s has type %s, expected one of: %v","messagePattern":"issue (.+?) has type (.+?), expected one of: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/validation/issue.go","lineNumber":276,"sourceCode":"\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\n// EpicHasOpenChildren validates that an epic does not have open children.\n// If the issue is an epic with open children, returns an error unless force is true.\n// Non-epic issues pass through without validation.\nfunc EpicHasOpenChildren(force bool, openChildCount int) IssueValidator {\n\treturn func(id string, issue *types.Issue) error {\n\t\tif issue == nil || force {\n\t\t\treturn nil\n\t\t}\n\t\tif issue.IssueType != types.TypeEpic {\n\t\t\treturn nil\n\t\t}\n\t\tif openChildCount > 0 {\n\t\t\treturn fmt.Errorf(\"epic %s has %d open child issue(s); close children first or use --force to override\", id, openChildCount)\n\t\t}\n\t\treturn nil","sourceCodeStart":258,"sourceCodeEnd":294,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/validation/issue.go#L258-L294","documentation":"This error is produced by the HasType validator when an operation is restricted to certain issue types (bug, feature, task, epic, chore) but the target issue's IssueType is not among the allowed types. It names the actual type and the permitted set, so callers can correct either the data or the constraint. It enforces type-specific rules such as only epics being able to receive children.","triggerScenarios":"Calling an operation that runs HasType(allowed...) on an issue whose issue.IssueType is outside the allowed slice (e.g. attempting an epic-only operation on a task or bug).","commonSituations":"Scripts that assume all IDs in a list are epics when some are tasks; type changed via edit after the ID was captured; new issue types introduced upstream that the validation list does not include; user typos selecting the wrong issue ID.","solutions":["Verify the issue's IssueType before the operation and skip/branch on non-matching types","Add the legitimate type(s) to the allowed list passed to HasType if the operation actually supports them","Correct the issue's type via update if it was set wrongly","Re-check ID selection in scripts/automation to ensure the right issue is targeted"],"exampleFix":"// before\nValidate(id, issue, HasType(types.TypeEpic)) // fails for task\n// after\nif issue.IssueType == types.TypeEpic {\n    Validate(id, issue, HasType(types.TypeEpic))\n}","handlingStrategy":"type-guard","validationCode":"func isType(issue *types.Issue, allowed ...types.IssueType) bool {\n    if issue == nil {\n        return false\n    }\n    for _, t := range allowed {\n        if issue.IssueType == t {\n            return true\n        }\n    }\n    return false\n}","typeGuard":"func isEpic(issue *types.Issue) bool {\n    return issue != nil && issue.IssueType == types.TypeEpic\n}","tryCatchPattern":"if err := validate(id, issue); err != nil {\n    if strings.Contains(err.Error(), \"has type\") {\n        log.Warnf(\"skipping %s: wrong type\", id)\n        return nil\n    }\n    return err\n}","preventionTips":["Branch on issue.IssueType before type-specific operations (epic-only, bug-only)","Filter ID lists by type before applying type-restricted bulk operations","Re-check an issue's type after any edit that can change it","Never hardcode assumptions that a stored ID refers to a specific type"],"tags":["validation","issue-type","precondition"],"backgroundTag":"invalid-issue-type","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}