{"record":{"id":"6cf5750410423b7c","repo":"gastownhall/beads","slug":"failed-to-scan-existing-issues-for-prefix-q-w","errorCode":null,"errorMessage":"failed to scan existing issues for prefix %q: %w","messagePattern":"failed to scan existing issues for prefix %q: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/issueops/helpers.go","lineNumber":284,"sourceCode":"\treturn fmt.Sprintf(\"%s-%d\", prefix, nextID), nil\n}\n\n// SeedCounterFromExistingIssuesTx scans existing issues to find the highest numeric suffix\n// for the given prefix, then seeds the issue_counter table if no row exists yet.\nfunc SeedCounterFromExistingIssuesTx(ctx context.Context, tx DBTX, prefix string) error {\n\tvar existing int\n\terr := tx.QueryRowContext(ctx, \"SELECT last_id FROM issue_counter WHERE prefix = ?\", prefix).Scan(&existing)\n\tif err == nil {\n\t\treturn nil // already seeded\n\t}\n\tif err != sql.ErrNoRows {\n\t\treturn fmt.Errorf(\"failed to check existing counter for prefix %q: %w\", prefix, err)\n\t}\n\n\t// Find max numeric suffix among existing issues\n\trows, err := tx.QueryContext(ctx, `SELECT id FROM issues WHERE id LIKE CONCAT(?, '-%')`, prefix)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to scan existing issues for prefix %q: %w\", prefix, err)\n\t}\n\tdefer rows.Close()\n\n\tmaxNum := 0\n\tpfxDash := prefix + \"-\"\n\tfor rows.Next() {\n\t\tvar id string\n\t\tif err := rows.Scan(&id); err != nil {\n\t\t\tcontinue\n\t\t}\n\t\tsuffix := strings.TrimPrefix(id, pfxDash)\n\t\tif strings.Contains(suffix, \".\") {\n\t\t\tcontinue // skip child IDs\n\t\t}\n\t\tif n, err := strconv.Atoi(suffix); err == nil && n > maxNum {\n\t\t\tmaxNum = n\n\t\t}\n\t}","sourceCodeStart":266,"sourceCodeEnd":302,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/issueops/helpers.go#L266-L302","documentation":"The query 'SELECT id FROM issues WHERE id LIKE CONCAT(?, '-%')' used to discover the highest existing issue number for a prefix failed at execution time. The wrapper is purely contextual; the wrapped driver error carries the actual cause.","triggerScenarios":"SeedCounterFromExistingIssuesTx (via NextCounterIDTx) on an unseeded prefix: tx.QueryContext on the issues table fails — table missing, CONCAT/LIKE incompatibility with the driver, connection error, or transaction already aborted by a prior error.","commonSituations":"Schema drift (issues table renamed/absent); using a driver that doesn't support CONCAT in LIKE patterns; issuing the call on a transaction that earlier failed and was invalidated.","solutions":["Read the wrapped error: if the tx was invalidated by an earlier failure, restart the whole operation in a new transaction.","Run schema migrations to ensure the issues table exists with expected columns.","If the driver lacks CONCAT support (non-Dolt SQLite backends), ensure you are using the correct storage driver for your database.","Retry on transient connection errors; check DB connectivity logs."],"exampleFix":"// before: reusing a failed tx\nif err != nil { return err } // earlier failure left tx dead\nrows, err := tx.QueryContext(...) // 'failed to scan existing issues'\n// after: abort and retry the entire unit in a fresh transaction\nif err != nil { return retryWithNewTx(op) }","handlingStrategy":"retry","validationCode":"if _, err := tx.QueryContext(ctx, \"SELECT 1 FROM issues LIMIT 1\"); err != nil {\n    return fmt.Errorf(\"issues table unavailable: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"if err != nil && strings.Contains(err.Error(), \"failed to scan existing issues\") {\n    // abandon the poisoned tx and retry in a fresh one\n    tx.Rollback()\n    return retryWithFreshTx(ctx, op)\n}","preventionTips":["Never continue using a transaction after an error; roll back and start fresh.","Run migrations so the issues table and expected columns exist.","Use the Dolt driver for Dolt databases so CONCAT-based LIKE patterns are supported."],"tags":["database","query","transaction","go"],"backgroundTag":"sql-query-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}