{"record":{"id":"e16ee2c4dc51cd63","repo":"gastownhall/beads","slug":"scan-status-w-e16ee2","errorCode":null,"errorMessage":"scan status: %w","messagePattern":"scan status: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/versioncontrolops/version_control.go","lineNumber":34,"sourceCode":"// Status returns the current Dolt working set status (staged and unstaged changes).\nfunc Status(ctx context.Context, db DBConn) (*storage.Status, error) {\n\trows, err := db.QueryContext(ctx, \"SELECT table_name, staged, status FROM dolt_status\")\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"get status: %w\", err)\n\t}\n\tdefer rows.Close()\n\n\tstatus := &storage.Status{\n\t\tStaged:   make([]storage.StatusEntry, 0),\n\t\tUnstaged: make([]storage.StatusEntry, 0),\n\t}\n\n\tfor rows.Next() {\n\t\tvar tableName string\n\t\tvar staged bool\n\t\tvar statusStr string\n\t\tif err := rows.Scan(&tableName, &staged, &statusStr); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"scan status: %w\", err)\n\t\t}\n\t\tentry := storage.StatusEntry{Table: tableName, Status: statusStr}\n\t\tif staged {\n\t\t\tstatus.Staged = append(status.Staged, entry)\n\t\t} else {\n\t\t\tstatus.Unstaged = append(status.Unstaged, entry)\n\t\t}\n\t}\n\treturn status, rows.Err()\n}\n\n// Log returns recent commit history up to limit entries.\n// If limit is 0 or negative, all entries are returned.\nfunc Log(ctx context.Context, db DBConn, limit int) ([]storage.CommitInfo, error) {\n\tvar query string\n\tvar args []interface{}\n\tif limit > 0 {\n\t\tquery = \"SELECT commit_hash, committer, email, date, message FROM dolt_log ORDER BY date DESC LIMIT ?\"","sourceCodeStart":16,"sourceCodeEnd":52,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/versioncontrolops/version_control.go#L16-L52","documentation":"Status wraps a failed rows.Scan into (tableName string, staged bool, statusStr string) as \"scan status: <underlying>\". The library throws it because a row returned by dolt_status did not match the expected three-column shape or types. Since dolt_status's schema is fixed by the Dolt engine, this usually indicates a Dolt version whose dolt_status columns differ, or a NULL value where a string is expected.","triggerScenarios":"A Dolt engine version returns dolt_status with different column order/types; a row contains NULL in table_name or status; the driver returns a type Go's Scan cannot convert into string/bool (e.g. status as []byte with unexpected encoding).","commonSituations":"Upgrading or downgrading the embedded Dolt engine so the dolt_status schema drifts; mixing driver versions (go-sql-driver/mysql) incompatible with the engine's result encoding.","solutions":["Check the installed Dolt engine version against the one the library was built for; align versions.","Run SELECT table_name, staged, status FROM dolt_status manually to inspect actual column names/types.","If columns drifted, pin the engine to a supported version rather than editing this query locally.","Look at the wrapped error text (e.g. 'converting NULL to string is unsupported') to identify which column/row misbehaves."],"exampleFix":"// before\n// engine v0.9 schema: (staged, table_name, status) — scan mismatch\nvar tableName string; var staged bool; var statusStr string\nrows.Scan(&tableName, &staged, &statusStr)\n// after\n// pin the supported Dolt engine version so dolt_status is (table_name, staged, status)\nrows.Scan(&tableName, &staged, &statusStr) // now matches","handlingStrategy":"validation","validationCode":"// probe dolt_status shape once at startup\nrows, err := db.QueryContext(ctx, \"SELECT table_name, staged, status FROM dolt_status LIMIT 1\")\nif err != nil { return fmt.Errorf(\"dolt_status incompatible: %w\", err) }\nrows.Close()","typeGuard":null,"tryCatchPattern":"st, err := versioncontrolops.Status(ctx, db)\nif err != nil && strings.HasPrefix(err.Error(), \"scan status\") {\n    return fmt.Errorf(\"dolt_status schema drifted; check Dolt engine version: %w\", err)\n}","preventionTips":["Pin the embedded Dolt engine to the version the library was built and tested against.","After engine upgrades, run a smoke Status/Log call before real work.","Keep the go-sql-driver/mysql version aligned with the engine's wire protocol.","When the wrapped error mentions NULL conversion, look for commits with incomplete metadata as the trigger row."],"tags":["dolt","sql","scan","schema-mismatch"],"backgroundTag":"sql-scan-type-mismatch","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}