gastownhall/beads · error

validation failed for issue %s: %w

Error message

validation failed for issue %s: %w

What it means

PrepareIssueForInsert runs the final domain validation on an issue before it is written, including validation against configured custom statuses and custom types via ValidateWithCustom. If the issue violates any schema/domain rule (invalid status, type, priority, missing required fields, bad dates), the underlying validation error is wrapped with the issue ID so the caller knows which record failed. The insert is aborted; nothing is written.

Source

Thrown at internal/storage/issueops/create.go:558

	}
	if issue.UpdatedAt.IsZero() {
		issue.UpdatedAt = now
	} else {
		issue.UpdatedAt = issue.UpdatedAt.UTC()
	}

	// Ensure closed issues have a closed_at timestamp.
	if issue.Status == types.StatusClosed && issue.ClosedAt == nil {
		maxTime := issue.CreatedAt
		if issue.UpdatedAt.After(maxTime) {
			maxTime = issue.UpdatedAt
		}
		closedAt := maxTime.Add(time.Second)
		issue.ClosedAt = &closedAt
	}

	if err := issue.ValidateWithCustom(customStatuses, customTypes); err != nil {
		return fmt.Errorf("validation failed for issue %s: %w", issue.ID, err)
	}
	if issue.ContentHash == "" {
		issue.ContentHash = issue.ComputeContentHash()
	}
	return nil
}

// ValidateIssueIDPrefix validates that the issue ID matches the configured prefix
// or any of the allowed_prefixes.
func ValidateIssueIDPrefix(id, prefix, allowedPrefixes string) error {
	if strings.HasPrefix(id, prefix+"-") {
		return nil
	}
	if allowedPrefixes != "" {
		for _, allowed := range strings.Split(allowedPrefixes, ",") {
			allowed = strings.TrimSpace(allowed)
			if allowed != "" && strings.HasPrefix(id, allowed+"-") {
				return nil

View on GitHub (pinned to 71377f2769)

Solutions

  1. Read the wrapped inner error (%w) to see the exact field that failed validation, then fix that field on the issue before inserting.
  2. Pass the repo's custom statuses/types (from config) as customStatuses/customTypes to PrepareIssueForInsert so legitimate custom values validate.
  3. Add the missing custom status/type to the repo configuration (.beads config) if the value is intentionally used.
  4. Run a pre-insert validation (issue.Validate()) on constructed issues to catch problems before entering the transaction.

Example fix

// before
issue := &types.Issue{Title: "Fix bug", Status: "in_review"}
_, err := issueops.CreateIssueInTxWithResult(ctx, tx, issue, opts) // fails: unknown status
// after
issue := &types.Issue{Title: "Fix bug", Status: "in_progress"} // or register "in_review" as a custom status
_, err := issueops.CreateIssueInTxWithResult(ctx, tx, issue, opts)
Defensive patterns

Strategy: validation

Validate before calling

if err := issue.ValidateWithCustom(customStatuses, customTypes); err != nil {
    return fmt.Errorf("issue %s invalid before create: %w", issue.ID, err)
}

Type guard

func isValidIssue(issue *types.Issue, statuses, issueTypes []string) bool {
    return issue != nil && issue.Title != "" &&
        slices.Contains(statuses, issue.Status) &&
        slices.Contains(issueTypes, issue.Type)
}

Try / catch

if err := createIssue(issue); err != nil {
    if strings.Contains(err.Error(), "validation failed for issue") {
        log.Warnw("issue rejected by domain validation", "id", issue.ID, "cause", err)
        return errSkipRecord
    }
    return err
}

Prevention

When it happens

Trigger: Calling CreateIssueInTxWithResult / PromoteFromEphemeralInTx / PreparePublicCreateRequest with an Issue whose Status or Type is not in the builtin set and not in the customStatuses/customTypes lists passed in, or which otherwise fails Issue.ValidateWithCustom (e.g. empty title, invalid priority).

Common situations: Importing JSONL exported from a repo that defined custom statuses/types not configured in the target repo; hand-crafted issue structs with a typo'd status ('oprn' vs 'open'); a repo whose config was changed to remove a custom type still referenced by old data; constructing issues programmatically without setting required fields.

Related errors


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