gastownhall/beads · error
issue %s has type %s, expected one of: %v
Error message
issue %s has type %s, expected one of: %v
What it means
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.
Source
Thrown at internal/validation/issue.go:276
return nil
}
}
return fmt.Errorf("issue %s has status %s, expected one of: %v", id, issue.Status, allowed)
}
}
// HasType validates that an issue has one of the allowed types.
func HasType(allowed ...types.IssueType) IssueValidator {
return func(id string, issue *types.Issue) error {
if issue == nil {
return nil
}
for _, t := range allowed {
if issue.IssueType == t {
return nil
}
}
return fmt.Errorf("issue %s has type %s, expected one of: %v", id, issue.IssueType, allowed)
}
}
// EpicHasOpenChildren validates that an epic does not have open children.
// If the issue is an epic with open children, returns an error unless force is true.
// Non-epic issues pass through without validation.
func EpicHasOpenChildren(force bool, openChildCount int) IssueValidator {
return func(id string, issue *types.Issue) error {
if issue == nil || force {
return nil
}
if issue.IssueType != types.TypeEpic {
return nil
}
if openChildCount > 0 {
return fmt.Errorf("epic %s has %d open child issue(s); close children first or use --force to override", id, openChildCount)
}
return nilView on GitHub (pinned to 71377f2769)
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
Example fix
// before
Validate(id, issue, HasType(types.TypeEpic)) // fails for task
// after
if issue.IssueType == types.TypeEpic {
Validate(id, issue, HasType(types.TypeEpic))
} Defensive patterns
Strategy: type-guard
Validate before calling
func isType(issue *types.Issue, allowed ...types.IssueType) bool {
if issue == nil {
return false
}
for _, t := range allowed {
if issue.IssueType == t {
return true
}
}
return false
} Type guard
func isEpic(issue *types.Issue) bool {
return issue != nil && issue.IssueType == types.TypeEpic
} Try / catch
if err := validate(id, issue); err != nil {
if strings.Contains(err.Error(), "has type") {
log.Warnf("skipping %s: wrong type", id)
return nil
}
return err
} Prevention
- 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
When it happens
Trigger: 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).
Common situations: 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.
Related errors
- %s is not a gate issue (type=%s)
- %w: invalid issue type %v
- %w: invalid issue type %s
- invalid issue type: %s
- issue %s has status %s, expected one of: %v
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/a27e53866b22ef4f.
Report an issue: GitHub.