gastownhall/beads · error

parsing %s: %w

Error message

parsing %s: %w

What it means

LoadProxiedServerClientInfo read the file successfully but json.Unmarshal could not parse its contents as ProxiedServerClientInfo, and wraps the JSON error. This means the file exists and is readable but is corrupt, truncated, empty, or was written in a different format than the current struct expects.

Source

Thrown at internal/configfile/proxied_server_client_info.go:37

	External    *ExternalDoltConfig `json:"external,omitempty"`
}

func ProxiedServerClientInfoPath(beadsDir string) string {
	return filepath.Join(beadsDir, ProxiedServerClientInfoFileName)
}

func LoadProxiedServerClientInfo(beadsDir string) (*ProxiedServerClientInfo, error) {
	path := ProxiedServerClientInfoPath(beadsDir)
	data, err := os.ReadFile(path) // #nosec G304 - controlled path
	if os.IsNotExist(err) {
		return nil, nil
	}
	if err != nil {
		return nil, fmt.Errorf("reading %s: %w", ProxiedServerClientInfoFileName, err)
	}
	var info ProxiedServerClientInfo
	if err := json.Unmarshal(data, &info); err != nil {
		return nil, fmt.Errorf("parsing %s: %w", ProxiedServerClientInfoFileName, err)
	}
	return &info, nil
}

func SaveProxiedServerClientInfo(beadsDir string, info *ProxiedServerClientInfo) error {
	if info == nil {
		info = &ProxiedServerClientInfo{}
	}
	data, err := json.MarshalIndent(info, "", "  ")
	if err != nil {
		return fmt.Errorf("marshaling %s: %w", ProxiedServerClientInfoFileName, err)
	}
	path := ProxiedServerClientInfoPath(beadsDir)
	if err := os.WriteFile(path, data, 0o600); err != nil {
		return fmt.Errorf("writing %s: %w", ProxiedServerClientInfoFileName, err)
	}
	return nil
}

View on GitHub (pinned to 71377f2769)

Solutions

  1. Validate the JSON (jq . <file>) to see the exact syntax error at the wrapped offset; fix or restore it.
  2. Delete the corrupt file and restart/reattach the proxied server so SaveProxiedServerClientInfo regenerates it: rm -f .beads/proxied_server_client_info.json.
  3. If you hand-edited it, restore valid JSON matching ProxiedServerClientInfo fields (strings for IDs/addresses, etc.).
  4. Check for a version mismatch — upgrade or downgrade bd so the reader matches the writer's format.

Example fix

// before
{"host": "127.0.0.1", "port":    // truncated
// after
# rm -f .beads/proxied_server_client_info.json && bd <start-server-cmd>
{"host": "127.0.0.1", "port": 50051}
Defensive patterns

Strategy: try-catch

Validate before calling

path := filepath.Join(beadsDir, configfile.ProxiedServerClientInfoFileName)
if data, err := os.ReadFile(path); err == nil {
    var probe map[string]any
    if json.Unmarshal(data, &probe) != nil {
        os.Remove(path) // let the server regenerate it
    }
}

Try / catch

info, err := configfile.LoadProxiedServerClientInfo(beadsDir)
if err != nil {
    var jsonErr *json.SyntaxError
    if errors.As(err, &jsonErr) {
        log.Printf("corrupt proxied server info at offset %d: %v — regenerating", jsonErr.Offset, jsonErr)
        os.Remove(filepath.Join(beadsDir, configfile.ProxiedServerClientInfoFileName))
    }
    return err
}

Prevention

When it happens

Trigger: Calling LoadProxiedServerClientInfo when the JSON file contains invalid syntax (truncated write, manual edit), is empty (0 bytes), or its fields/types no longer match the ProxiedServerClientInfo struct after a version change.

Common situations: Process killed mid-write leaving a partial file; hand-editing the JSON and breaking syntax; upgrading/downgrading bd so the stored shape changed; file corrupted by disk issues or sync tools (Dropbox etc.).

Related errors


AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30). Data as JSON: /api/errors/8bb81c9010b66d34. Report an issue: GitHub.