gastownhall/beads · error
parse %s: %w
Error message
parse %s: %w
What it means
PersistedRemotes parses .dolt/repo_state.json as JSON after reading it. If json.Unmarshal fails, this error wraps the parse failure with the file path, indicating the Dolt repo state file is malformed. The library cannot enumerate persisted remotes until the file is valid JSON.
Source
Thrown at internal/storage/doltutil/remotes.go:104
// means "not a dolt repository here" and returns (nil, nil); an unreadable or
// unparseable file returns an error so callers can tell "definitely none"
// from "could not tell". Results are sorted by name.
func PersistedRemotes(dbPath string) ([]storage.RemoteInfo, error) {
path := filepath.Join(dbPath, ".dolt", "repo_state.json")
data, err := os.ReadFile(path) // #nosec G304 -- repo-local dolt state file
if err != nil {
if os.IsNotExist(err) {
return nil, nil
}
return nil, fmt.Errorf("read %s: %w", path, err)
}
var state struct {
Remotes map[string]struct {
URL string `json:"url"`
} `json:"remotes"`
}
if err := json.Unmarshal(data, &state); err != nil {
return nil, fmt.Errorf("parse %s: %w", path, err)
}
remotes := make([]storage.RemoteInfo, 0, len(state.Remotes))
for name, r := range state.Remotes {
remotes = append(remotes, storage.RemoteInfo{Name: name, URL: r.URL})
}
sort.Slice(remotes, func(i, j int) bool { return remotes[i].Name < remotes[j].Name })
return remotes, nil
}
// ListCLIRemotes parses `dolt remote -v` output from the given database
// directory. This is a read-only guard for deciding whether CLI push/pull/fetch
// can safely run from that directory; remote mutation still goes through SQL.
func ListCLIRemotes(dbPath string) ([]storage.RemoteInfo, error) {
ctx, cancel := context.WithTimeout(context.Background(), listCLIRemotesTimeout(dbPath))
defer cancel()
cmd := exec.CommandContext(ctx, "dolt", "remote", "-v") // #nosec G204 -- fixed command
cmd.Dir = dbPath
out, err := cmd.CombinedOutput()View on GitHub (pinned to 71377f2769)
Solutions
- Inspect <dbPath>/.dolt/repo_state.json and fix the JSON syntax manually.
- Restore the file from a backup or a healthy clone of the same repo.
- Let Dolt regenerate repo state (re-add remotes via 'dolt remote add') after moving the corrupt file aside.
- Check disk health if corruption recurs.
Example fix
// before mv .dolt/repo_state.json .dolt/repo_state.json.bak # corrupt // after mv .dolt/repo_state.json.bak .dolt/repo_state.json # restored valid JSON, then verify: dolt remote -v
Defensive patterns
Strategy: validation
Validate before calling
data, err := os.ReadFile(filepath.Join(dbPath, ".dolt", "repo_state.json"))
if err == nil && json.Valid(data) { /* safe to call PersistedRemotes */ } Try / catch
remotes, err := doltutil.PersistedRemotes(dbPath)
if err != nil && strings.HasPrefix(err.Error(), "parse ") {
os.Rename(statePath, statePath+".corrupt") // quarantine and rebuild
remotes = nil
} Prevention
- Never hand-edit repo_state.json
- Shut down cleanly (no kill -9) to avoid truncated writes
- Keep backups of the .dolt directory
- Check disk health if corruption recurs
When it happens
Trigger: Calling PersistedRemotes when repo_state.json is corrupted: truncated write during a crash, manual editing mistakes, or encoding issues.
Common situations: Power loss / kill -9 mid-write; user hand-edited the file; Dolt version format change; disk corruption.
Understand the failure class
Background: JSON parse error: "Unexpected token" / "not valid JSON" / "failed to parse" — what JSON parsers are really complaining about — this error's family across 45 libraries.
Related errors
- multiple .doltcfg directories detected
- dolt path is not executable
- resolve proxied server root: %w
- creating .bd-dolt-ok marker: %w
- failed to remove Dolt database: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/8235c13ec8ccc15b.
Report an issue: GitHub.