gastownhall/beads · error

prefix validation failed for %s: %w

Error message

prefix validation failed for %s: %w

What it means

assignCreateIssueIDInTx validates a newly generated issue ID against the configured prefix rules via ValidateIssueIDPrefix, refusing IDs whose prefix is not in AllowedPrefixes (or not matching ConfigPrefix). Callers can bypass this with Opts.SkipPrefixValidation. The error is wrapped as "prefix validation failed for %s: %w" naming the rejected ID.

Source

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

		issueTable, _ := TableRouting(issue)
		prefix := bc.ConfigPrefix
		if issue.PrefixOverride != "" {
			prefix = issue.PrefixOverride
		} else if issue.IDPrefix != "" {
			prefix = bc.ConfigPrefix + "-" + issue.IDPrefix
		} else if IsWisp(issue) {
			prefix = bc.ConfigPrefix + "-wisp"
		}
		var err error
		issue.ID, err = GenerateIssueIDInTable(ctx, tx, issueTable, prefix, issue, actor)
		if err != nil {
			return fmt.Errorf("failed to generate issue ID: %w", err)
		}
		return nil
	}
	if !bc.Opts.SkipPrefixValidation {
		if err := ValidateIssueIDPrefix(issue.ID, bc.ConfigPrefix, bc.AllowedPrefixes); err != nil {
			return fmt.Errorf("prefix validation failed for %s: %w", issue.ID, err)
		}
	}
	return nil
}

// CreateIssuesResult reports side effects that callers need for selective
// Dolt staging after CreateIssuesInTxWithResult returns.
type CreateIssuesResult struct {
	ChangedTables             map[string]bool
	ChangedChildCounterTables map[string]bool
}

func (r *CreateIssuesResult) markChanged(table string) {
	if table == "" {
		return
	}
	if r.ChangedTables == nil {
		r.ChangedTables = map[string]bool{}

View on GitHub (pinned to 71377f2769)

Solutions

  1. Align the ID generation/config: set ConfigPrefix/AllowedPrefixes to include the prefix the ID actually uses.
  2. Set Opts.SkipPrefixValidation = true only if you deliberately accept foreign-prefix IDs (e.g. imports).
  3. Regenerate the ID with the correct prefix before insert.

Example fix

// before
bc := CreateIssueContext{ConfigPrefix: "bd", AllowedPrefixes: []string{"bd"}}
// ID "jira-123" -> prefix validation failed

// after
bc := CreateIssueContext{
	ConfigPrefix: "bd",
	AllowedPrefixes: []string{"bd", "jira"}, // accept imported prefixes
}
Defensive patterns

Strategy: validation

Validate before calling

if !slices.Contains(allowedPrefixes, prefixOf(issueID)) {
	return fmt.Errorf("prefix %q not allowed (allowed: %v)", prefixOf(issueID), allowedPrefixes)
}

Try / catch

if err := store.CreateIssue(ctx, issue); err != nil {
	if strings.HasPrefix(err.Error(), "prefix validation failed") {
		return fmt.Errorf("config/id prefix mismatch; fix prefix config or set SkipPrefixValidation: %w", err)
	}
	return err
}

Prevention

When it happens

Trigger: Creating an issue whose generated ID prefix (e.g. from a custom --prefix or imported ID) is not in the configured allowed prefixes; changing prefix config after issues were created with the old prefix; importing issues from another repo with foreign prefixes without SkipPrefixValidation.

Common situations: Teams renaming their issue prefix in config but having automation still creating issues under the old prefix; federated setups importing beads from multiple remotes with different prefixes; misconfigured .beads/beads.jsonp/config prefix setting.

Related errors


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