{"record":{"id":"67d7512e9289eb09","repo":"gastownhall/beads","slug":"failed-to-get-issue-from-s-w","errorCode":null,"errorMessage":"failed to get issue from %s: %w","messagePattern":"failed to get issue from (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/dolt/wisps.go","lineNumber":40,"sourceCode":"\treturn issueops.InsertIssueIntoTable(ctx, tx, table, issue)\n}\n\n// scanIssueFromTable scans a single issue from the specified table.\n//\n//nolint:gosec // G201: table is a hardcoded constant (\"issues\" or \"wisps\")\nfunc scanIssueFromTable(ctx context.Context, db *sql.DB, table, id string) (*types.Issue, error) {\n\trow := db.QueryRowContext(ctx, fmt.Sprintf(`\n\t\tSELECT %s\n\t\tFROM %s %s\n\t\tWHERE id = ?\n\t`, issueSelectColumns, table, sqlbuild.LeaseJoin(table)), id)\n\n\tissue, err := scanIssueFrom(row)\n\tif err == sql.ErrNoRows {\n\t\treturn nil, fmt.Errorf(\"%w: issue %s\", storage.ErrNotFound, id)\n\t}\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to get issue from %s: %w\", table, err)\n\t}\n\treturn issue, nil\n}\n\n// generateIssueIDInTable generates a unique ID, checking for collisions\n// in the specified table. Supports counter mode for non-ephemeral issues.\n//\n//nolint:gosec // G201: table is a hardcoded constant\nfunc generateIssueIDInTable(ctx context.Context, tx *sql.Tx, table, prefix string, issue *types.Issue, actor string) (string, error) {\n\t// Counter mode only applies to the issues table (not wisps).\n\tif table == \"issues\" {\n\t\tcounterMode, err := isCounterModeTx(ctx, tx)\n\t\tif err != nil {\n\t\t\treturn \"\", err\n\t\t}\n\t\tif counterMode {\n\t\t\treturn nextCounterIDTx(ctx, tx, prefix)\n\t\t}","sourceCodeStart":22,"sourceCodeEnd":58,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/dolt/wisps.go#L22-L58","documentation":"Returned by scanIssueFromTable when scanIssueFrom fails for a reason other than sql.ErrNoRows — i.e., the row was fetched but could not be scanned into the issue struct, or the query itself errored. The message includes the table name and wraps the underlying driver/scan error. Unlike the ErrNoRows case this indicates a genuine unexpected failure reading the issue.","triggerScenarios":"A SELECT from the wisps/issues table by ID succeeds in returning a row but scanIssueFrom fails: column/type mismatch after a schema change, NULL in a non-nullable-scanned column, or an underlying driver error during Scan/QueryRowContext.","commonSituations":"Running a newer bd binary against an older database (or vice versa) so issueSelectColumns doesn't match the actual table schema; corrupted rows; Dolt/driver version upgrades changing type mapping.","solutions":["Read the wrapped cause (%w) to see the exact scan/driver error","Confirm the table schema matches the binary's expected columns (issueSelectColumns); run any available schema migration (e.g. bd doctor / migrate)","Upgrade or downgrade bd so binary and database schema versions agree","If a row is corrupt, restore from Dolt history or re-export/import the issue"],"exampleFix":"// before\n// binary expects a column the DB lacks: scan fails with 'failed to get issue from wisps: ...'\n// after\n// run: bd doctor   (or the project's migrate step) to align schema, then retry the lookup","handlingStrategy":"try-catch","validationCode":"// check schema alignment before lookups\nrows, err := db.Query(`SHOW COLUMNS FROM wisps`)\nif err != nil {\n    return fmt.Errorf(\"wisps table missing or unreadable: %w\", err)\n}\n// compare against expected columns / run bd doctor","typeGuard":null,"tryCatchPattern":"issue, err := store.GetIssue(ctx, id)\nif err != nil {\n    var msg string\n    if !errors.Is(err, storage.ErrNotFound) && strings.Contains(err.Error(), \"failed to get issue from\") {\n        return fmt.Errorf(\"schema/driver problem reading issue: %w\", err)\n    }\n    return err\n}","preventionTips":["Run bd doctor / migrations after every binary upgrade","Keep binary and database schema versions in sync","Back up via Dolt history before schema-affecting operations","Treat non-ErrNoRows scan failures as schema or corruption signals, and investigate the wrapped cause"],"tags":["database","scan","schema","go"],"backgroundTag":"row-scan-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}