gastownhall/beads · error
read issue_id_mode: %w
Error message
read issue_id_mode: %w
What it means
Wraps failure of cfgRepo.GetConfig(ctx, "issue_id_mode") inside mintTopLevelID for non-wisp issues. bd needs to know whether to use counter or hash IDs; the config read itself failed (not an invalid value — an unset/"counter"/anything falls through to hash mode).
Source
Thrown at internal/storage/domain/issue.go:1604
// mintTopLevelID generates a fresh top-level ID for an issue that has no
// ExplicitID and no ParentID. Honors counter mode for non-wisps (config key
// issue_id_mode=counter); otherwise uses adaptive hash-mode IDs that mirror
// issueops.GenerateIssueIDInTable. Reads issue.CreatedAt (caller must have
// stabilized it before this call so retries hash the same value).
func (u *issueUseCaseImpl) mintTopLevelID(ctx context.Context, issue *types.Issue, actor string, useWisp bool) (string, error) {
prefix, err := u.resolveTopLevelPrefix(ctx, issue, useWisp)
if err != nil {
return "", err
}
// Counter mode applies only to the issues table — wisps always hash-mint
// because there is no wisp_counter table and ephemeral churn would make
// a monotonic counter meaningless.
if !useWisp {
mode, err := u.cfgRepo.GetConfig(ctx, "issue_id_mode")
if err != nil {
return "", fmt.Errorf("read issue_id_mode: %w", err)
}
if mode == "counter" {
n, err := u.issueRepo.NextCounterID(ctx, prefix)
if err != nil {
return "", err
}
return fmt.Sprintf("%s-%d", prefix, n), nil
}
}
cfg, err := u.cfgRepo.GetAdaptiveIDConfig(ctx)
if err != nil {
return "", fmt.Errorf("read adaptive id config: %w", err)
}
tableOpts := IssueTableOpts{UseWispsTable: useWisp}
count, err := u.issueRepo.CountForPrefix(ctx, prefix, tableOpts)
if err != nil {View on GitHub (pinned to 71377f2769)
Solutions
- Check DB connectivity and retry the create.
- Ensure the config table exists and is initialized (bd init / bd doctor).
- Explicitly set the mode to silence ambiguity: bd config set issue_id_mode hash (or counter).
- Inspect the wrapped error for a driver-level cause and fix storage.
Defensive patterns
Strategy: retry
Validate before calling
// probe config availability before minting
if _, err := cfgRepo.GetConfig(ctx, "issue_id_mode"); err != nil {
return fmt.Errorf("config store unreachable: %w", err)
} Try / catch
if err != nil {
if isTransientStorageErr(err) {
return retryWithBackoff(func() error { return mintID(ctx, issue) })
}
return fmt.Errorf("issue_id_mode unreadable: %w", err)
} Prevention
- Initialize workspaces with bd init before creating issues.
- Retry transient DB errors with exponential backoff.
- Keep schema migrations current with bd version.
- Set explicit issue_id_mode in config to make intent auditable.
When it happens
Trigger: Minting a new top-level regular (non-wisp) issue ID while the issue_id_mode config read errors: storage down, config table missing, canceled context.
Common situations: Database outage during create; uninitialized workspace; version/schema mismatch between bd binary and DB config table.
Related errors
- read issue_prefix: %w
- read adaptive id config: %w
- failed to set routing.contributor: %w
- failed to set sync branch: %w
- failed to enable team mode: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/9ebfc5b0764ba8ed.
Report an issue: GitHub.