{"record":{"id":"9ebfc5b0764ba8ed","repo":"gastownhall/beads","slug":"read-issue-id-mode-w","errorCode":null,"errorMessage":"read issue_id_mode: %w","messagePattern":"read issue_id_mode: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/domain/issue.go","lineNumber":1604,"sourceCode":"\n// mintTopLevelID generates a fresh top-level ID for an issue that has no\n// ExplicitID and no ParentID. Honors counter mode for non-wisps (config key\n// issue_id_mode=counter); otherwise uses adaptive hash-mode IDs that mirror\n// issueops.GenerateIssueIDInTable. Reads issue.CreatedAt (caller must have\n// stabilized it before this call so retries hash the same value).\nfunc (u *issueUseCaseImpl) mintTopLevelID(ctx context.Context, issue *types.Issue, actor string, useWisp bool) (string, error) {\n\tprefix, err := u.resolveTopLevelPrefix(ctx, issue, useWisp)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\n\t// Counter mode applies only to the issues table — wisps always hash-mint\n\t// because there is no wisp_counter table and ephemeral churn would make\n\t// a monotonic counter meaningless.\n\tif !useWisp {\n\t\tmode, err := u.cfgRepo.GetConfig(ctx, \"issue_id_mode\")\n\t\tif err != nil {\n\t\t\treturn \"\", fmt.Errorf(\"read issue_id_mode: %w\", err)\n\t\t}\n\t\tif mode == \"counter\" {\n\t\t\tn, err := u.issueRepo.NextCounterID(ctx, prefix)\n\t\t\tif err != nil {\n\t\t\t\treturn \"\", err\n\t\t\t}\n\t\t\treturn fmt.Sprintf(\"%s-%d\", prefix, n), nil\n\t\t}\n\t}\n\n\tcfg, err := u.cfgRepo.GetAdaptiveIDConfig(ctx)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"read adaptive id config: %w\", err)\n\t}\n\ttableOpts := IssueTableOpts{UseWispsTable: useWisp}\n\n\tcount, err := u.issueRepo.CountForPrefix(ctx, prefix, tableOpts)\n\tif err != nil {","sourceCodeStart":1586,"sourceCodeEnd":1622,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/domain/issue.go#L1586-L1622","documentation":"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).","triggerScenarios":"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.","commonSituations":"Database outage during create; uninitialized workspace; version/schema mismatch between bd binary and DB config table.","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."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// probe config availability before minting\nif _, err := cfgRepo.GetConfig(ctx, \"issue_id_mode\"); err != nil {\n    return fmt.Errorf(\"config store unreachable: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"if err != nil {\n    if isTransientStorageErr(err) {\n        return retryWithBackoff(func() error { return mintID(ctx, issue) })\n    }\n    return fmt.Errorf(\"issue_id_mode unreadable: %w\", err)\n}","preventionTips":["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."],"tags":["config","id-generation","storage"],"backgroundTag":"missing-config-value","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}