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 nil

View on GitHub (pinned to 71377f2769)

Solutions

  1. Verify the issue's IssueType before the operation and skip/branch on non-matching types
  2. Add the legitimate type(s) to the allowed list passed to HasType if the operation actually supports them
  3. Correct the issue's type via update if it was set wrongly
  4. 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

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


AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30). Data as JSON: /api/errors/a27e53866b22ef4f. Report an issue: GitHub.