gastownhall/beads · error
marshaling %s: %w
Error message
marshaling %s: %w
What it means
SaveProxiedServerClientInfo serializes the ProxiedServerClientInfo struct to JSON before writing it to the .beads directory. This error wraps any json.MarshalIndent failure, prefixed with the sidecar filename so the developer knows which file failed to build. Marshaling of this plain struct should essentially never fail in practice, so this is a defensive wrapper.
Source
Thrown at internal/configfile/proxied_server_client_info.go:48
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
}
func resolveSidecarPath(beadsDir, p string) string {
if p == "" {
return ""
}
if filepath.IsAbs(p) {
return p
}
return filepath.Join(beadsDir, p)
}
View on GitHub (pinned to 71377f2769)
Solutions
- Inspect the wrapped inner error (%w) to identify the field that failed to marshal.
- Check for recent changes to the ProxiedServerClientInfo struct — remove or fix fields with unsupported types or broken custom MarshalJSON methods.
- Verify no custom MarshalJSON on the struct returns non-nil errors.
Example fix
// before
type ProxiedServerClientInfo struct {
Conn func() net.Conn `json:"conn"`
}
// after
type ProxiedServerClientInfo struct {
Addr string `json:"addr"`
} Defensive patterns
Strategy: try-catch
Validate before calling
if info != nil {
if _, err := json.Marshal(info); err != nil {
// reject/fix info before calling SaveProxiedServerClientInfo
}
} Try / catch
if err := configfile.SaveProxiedServerClientInfo(beadsDir, info); err != nil {
var perr *json.UnsupportedTypeError
if errors.As(err, &perr) {
log.Fatalf("unsupported field type %v in client info", perr.Type)
}
return fmt.Errorf("saving proxied server client info: %w", err)
} Prevention
- Keep ProxiedServerClientInfo limited to JSON-safe scalar/string types.
- Never add custom MarshalJSON that can fail on this struct.
- Add a round-trip test that marshals a populated ProxiedServerClientInfo.
When it happens
Trigger: Calling SaveProxiedServerClientInfo with an *ProxiedServerClientInfo that json.Marshal cannot serialize — practically only possible with unsupported types (channels, funcs, cycles) injected via custom MarshalJSON on the struct's fields.
Common situations: A new field was added to ProxiedServerClientInfo with a type that fails marshaling, or a custom MarshalJSON implementation returns an error; seen during development, not in normal operation.
Related errors
- failed to marshal backup state: %w
- failed to marshal issue %s: %w
- failed to write JSON: %w
- marshaling Linear milestone metadata: %w
- failed to marshal interactions log entry: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/63a8a27e7d25dc97.
Report an issue: GitHub.