{"record":{"id":"97eaba3cd535e4c1","repo":"gastownhall/beads","slug":"scan-commit-w","errorCode":null,"errorMessage":"scan commit: %w","messagePattern":"scan commit: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/versioncontrolops/version_control.go","lineNumber":67,"sourceCode":"\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 ?\"\n\t\targs = []interface{}{limit}\n\t} else {\n\t\tquery = \"SELECT commit_hash, committer, email, date, message FROM dolt_log ORDER BY date DESC\"\n\t}\n\trows, err := db.QueryContext(ctx, query, args...)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"get log: %w\", err)\n\t}\n\tdefer rows.Close()\n\n\tvar commits []storage.CommitInfo\n\tfor rows.Next() {\n\t\tvar c storage.CommitInfo\n\t\tif err := rows.Scan(&c.Hash, &c.Author, &c.Email, &c.Date, &c.Message); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"scan commit: %w\", err)\n\t\t}\n\t\tcommits = append(commits, c)\n\t}\n\treturn commits, rows.Err()\n}\n\n// CommitExists checks whether a commit hash (or prefix) exists in dolt_log.\n// Returns false for empty strings or malformed input.\nfunc CommitExists(ctx context.Context, db DBConn, commitHash string) (bool, error) {\n\tif commitHash == \"\" {\n\t\treturn false, nil\n\t}\n\tif err := issueops.ValidateRef(commitHash); err != nil {\n\t\treturn false, nil\n\t}\n\n\tvar count int\n\terr := db.QueryRowContext(ctx, `","sourceCodeStart":49,"sourceCodeEnd":85,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/versioncontrolops/version_control.go#L49-L85","documentation":"Log wraps a failed rows.Scan into storage.CommitInfo fields (Hash, Author, Email, Date, Message) as \"scan commit: <underlying>\". The library throws it because a dolt_log row's column types or names did not match the five expected values. Like the status scan error, this points at Dolt engine schema drift for dolt_log (e.g. different date column type) or an unconvertible/NULL value.","triggerScenarios":"Engine version where dolt_log columns differ (e.g. date returned as a type the driver maps to something Scan can't put into CommitInfo.Date); NULL in a NOT-NULL-assumed column; driver type-mapping incompatibility.","commonSituations":"Engine upgrade changing dolt_log's date/email column types; a commit with missing committer metadata from an unusual producer; mismatched go-sql-driver version.","solutions":["Run SELECT commit_hash, committer, email, date, message FROM dolt_log LIMIT 1 manually to see actual types.","Align the Dolt engine/driver versions with the ones the library expects.","If the date column type changed, pin the engine version or adapt CommitInfo scanning at the library level.","Read the wrapped error to identify the offending column and value."],"exampleFix":"// before\n// engine maps 'date' to a driver type Scan can't decode into c.Date\nrows.Scan(&c.Hash, &c.Author, &c.Email, &c.Date, &c.Message)\n// after\n// pin the supported Dolt engine version so 'date' decodes as time.Time\nrows.Scan(&c.Hash, &c.Author, &c.Email, &c.Date, &c.Message)","handlingStrategy":"validation","validationCode":"// verify dolt_log column shape before scanning\nrows, err := db.QueryContext(ctx, \"SELECT commit_hash, committer, email, date, message FROM dolt_log LIMIT 1\")\nif err != nil { return fmt.Errorf(\"dolt_log incompatible: %w\", err) }\ncols, _ := rows.Columns()\nrows.Close()\nwant := []string{\"commit_hash\", \"committer\", \"email\", \"date\", \"message\"}\nif !reflect.DeepEqual(cols, want) { return fmt.Errorf(\"dolt_log columns drifted: %v\", cols) }","typeGuard":null,"tryCatchPattern":"commits, err := versioncontrolops.Log(ctx, db, limit)\nif err != nil && strings.HasPrefix(err.Error(), \"scan commit\") {\n    return nil, fmt.Errorf(\"dolt_log row shape mismatch — check engine version: %w\", err)\n}","preventionTips":["Keep the Dolt engine version fixed; dolt_log column types (especially date) can change across releases.","Smoke-test Log with LIMIT 1 after any engine or driver upgrade.","Handle rows.Err() after iteration to catch late row errors, mirroring the library's pattern.","If a specific commit's metadata is NULL, re-commit with complete author info or skip that row in downstream processing."],"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"}