{"record":{"id":"63a8a27e7d25dc97","repo":"gastownhall/beads","slug":"marshaling-s-w","errorCode":null,"errorMessage":"marshaling %s: %w","messagePattern":"marshaling (.+?): %w","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/configfile/proxied_server_client_info.go","lineNumber":48,"sourceCode":"\t\treturn nil, nil\n\t}\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"reading %s: %w\", ProxiedServerClientInfoFileName, err)\n\t}\n\tvar info ProxiedServerClientInfo\n\tif err := json.Unmarshal(data, &info); err != nil {\n\t\treturn nil, fmt.Errorf(\"parsing %s: %w\", ProxiedServerClientInfoFileName, err)\n\t}\n\treturn &info, nil\n}\n\nfunc SaveProxiedServerClientInfo(beadsDir string, info *ProxiedServerClientInfo) error {\n\tif info == nil {\n\t\tinfo = &ProxiedServerClientInfo{}\n\t}\n\tdata, err := json.MarshalIndent(info, \"\", \"  \")\n\tif err != nil {\n\t\treturn fmt.Errorf(\"marshaling %s: %w\", ProxiedServerClientInfoFileName, err)\n\t}\n\tpath := ProxiedServerClientInfoPath(beadsDir)\n\tif err := os.WriteFile(path, data, 0o600); err != nil {\n\t\treturn fmt.Errorf(\"writing %s: %w\", ProxiedServerClientInfoFileName, err)\n\t}\n\treturn nil\n}\n\nfunc resolveSidecarPath(beadsDir, p string) string {\n\tif p == \"\" {\n\t\treturn \"\"\n\t}\n\tif filepath.IsAbs(p) {\n\t\treturn p\n\t}\n\treturn filepath.Join(beadsDir, p)\n}\n","sourceCodeStart":30,"sourceCodeEnd":66,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/configfile/proxied_server_client_info.go#L30-L66","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\ntype ProxiedServerClientInfo struct {\n    Conn func() net.Conn `json:\"conn\"`\n}\n// after\ntype ProxiedServerClientInfo struct {\n    Addr string `json:\"addr\"`\n}","handlingStrategy":"try-catch","validationCode":"if info != nil {\n    if _, err := json.Marshal(info); err != nil {\n        // reject/fix info before calling SaveProxiedServerClientInfo\n    }\n}","typeGuard":null,"tryCatchPattern":"if err := configfile.SaveProxiedServerClientInfo(beadsDir, info); err != nil {\n    var perr *json.UnsupportedTypeError\n    if errors.As(err, &perr) {\n        log.Fatalf(\"unsupported field type %v in client info\", perr.Type)\n    }\n    return fmt.Errorf(\"saving proxied server client info: %w\", err)\n}","preventionTips":["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."],"tags":["json","serialization","config-file"],"backgroundTag":"json-marshal-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}