{"record":{"id":"c42d07e2a0e84989","repo":"gastownhall/beads","slug":"iterate-dirty-config-diff-w","errorCode":null,"errorMessage":"iterate dirty config diff: %w","messagePattern":"iterate dirty config diff: %w","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/dolt/store.go","lineNumber":3200,"sourceCode":"\trows, err := conn.QueryContext(ctx,\n\t\t\"SELECT COALESCE(to_key, from_key) FROM dolt_diff('HEAD', 'WORKING', 'config')\")\n\tif err != nil {\n\t\treturn fmt.Errorf(\"inspect dirty config before pull: %w\", err)\n\t}\n\tdefer rows.Close()\n\n\tvar unsafe []string\n\tfor rows.Next() {\n\t\tvar key sql.NullString\n\t\tif err := rows.Scan(&key); err != nil {\n\t\t\treturn fmt.Errorf(\"scan dirty config key: %w\", err)\n\t\t}\n\t\tif key.Valid && !strings.HasPrefix(key.String, kvkeys.Prefix) {\n\t\t\tunsafe = append(unsafe, key.String)\n\t\t}\n\t}\n\tif err := rows.Err(); err != nil {\n\t\treturn fmt.Errorf(\"iterate dirty config diff: %w\", err)\n\t}\n\tif len(unsafe) > 0 {\n\t\treturn fmt.Errorf(\"refusing to auto-commit %d dirty internal config key(s) before pull: %s; \"+\n\t\t\t\"only user %s* keys auto-commit before a pull (GH#2455) — commit or revert \"+\n\t\t\t\"these explicitly with `bd dolt commit` first\", len(unsafe), strings.Join(unsafe, \", \"), kvkeys.Prefix)\n\t}\n\treturn nil\n}\n\n// CommitWithConfig creates a Dolt commit that includes the config table.\n// Use this instead of Commit when the caller intentionally modified config\n// (e.g., CommitPending after 'bd config set', 'bd init', or 'bd rename-prefix').\n// GH#2455: Commit() excludes config to prevent sweeping up stale changes.\nfunc (s *DoltStore) CommitWithConfig(ctx context.Context, message string) error {\n\treturn s.withCircuitWrite(ctx, func(ctx context.Context) error {\n\t\tconn, err := s.db.Conn(ctx)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"failed to acquire connection: %w\", err)","sourceCodeStart":3182,"sourceCodeEnd":3218,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/dolt/store.go#L3182-L3218","documentation":"Wraps a rows-scanning error from a SQL query that diffs the config table to find dirty internal config keys before a pull. It is thrown because the library cannot determine which config keys are dirty, so it must abort the pre-pull auto-commit check rather than guess.","triggerScenarios":"The config-diff query (iterating rows returned by a dolt diff/status-style query over config keys) fails mid-iteration — e.g. the underlying Dolt table query errored after some rows were read.","commonSituations":"Database connection drop during pull, Dolt server restart, schema/lock contention on the config table, or a corrupt working-set diff.","solutions":["Check Dolt server health and connectivity (bd dolt status).","Retry the pull once the connection is stable.","Inspect the wrapped cause (%w) for the specific driver error and address it (e.g. table lock, schema mismatch).","If schema-related, verify the beads database schema version matches your bd version."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// before triggering pre-pull commit\nif err := s.db.PingContext(ctx); err != nil {\n    return fmt.Errorf(\"dolt database unreachable before pull: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"var iterateErr *storageError\nif errors.As(err, &iterateErr) && isConnectionError(iterateErr) {\n    // back off and retry the pull once connectivity is restored\n}","preventionTips":["Keep the Dolt server healthy and monitored during sync operations.","Avoid killing bd mid-pull; use graceful shutdown.","Set generous context timeouts for pull/sync operations.","Watch for connection pool exhaustion under concurrent agents."],"tags":["dolt","database","iteration","pull"],"backgroundTag":"dolt-query-iteration-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}