{"record":{"id":"f4a82bf8f53e5657","repo":"sipeed/picoclaw","slug":"failed-to-decode-serialized-config-w","errorCode":null,"errorMessage":"failed to decode serialized config: %w","messagePattern":"failed to decode serialized config: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/picoclaw/internal/mcp/helpers.go","lineNumber":151,"sourceCode":"\t}\n\n\tclone.Tools = cfg.Tools\n\tclone.Tools.MCP = cfg.Tools.MCP\n\tclone.Tools.MCP.Servers = make(map[string]config.MCPServerConfig, len(cfg.Tools.MCP.Servers))\n\tfor name, server := range cfg.Tools.MCP.Servers {\n\t\tif server.Type != \"\" {\n\t\t\tserver.Type = config.NormalizeMCPTransportType(server.Type)\n\t\t}\n\t\tclone.Tools.MCP.Servers[name] = server\n\t}\n\n\treturn &clone\n}\n\nfunc validateConfigDocument(data []byte) error {\n\tvar instance map[string]any\n\tif err := json.Unmarshal(data, &instance); err != nil {\n\t\treturn fmt.Errorf(\"failed to decode serialized config: %w\", err)\n\t}\n\n\tschema, err := loadMCPConfigSchema()\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to load MCP config schema: %w\", err)\n\t}\n\n\tif err := schema.Validate(instance); err != nil {\n\t\treturn fmt.Errorf(\"config validation failed: %w\", err)\n\t}\n\n\treturn nil\n}\n\nfunc loadMCPConfigSchema() (*jsonschema.Resolved, error) {\n\tmcpConfigSchemaOnce.Do(func() {\n\t\tvar schema jsonschema.Schema\n\t\tif err := json.Unmarshal([]byte(mcpConfigSchemaJSON), &schema); err != nil {","sourceCodeStart":133,"sourceCodeEnd":169,"githubUrl":"https://github.com/sipeed/picoclaw/blob/49183d7e8daed0dba89ddbb6fcb60089401d9680/cmd/picoclaw/internal/mcp/helpers.go#L133-L169","documentation":"validateConfigDocument re-unmarshals the bytes it just produced (helpers.go:149-152). Failing here means the in-memory config serialized into something encoding/json cannot read back — practically an invariant break, since the data was marshaled moments earlier from the same structs. Not reachable through normal CLI usage.","triggerScenarios":"Custom MarshalJSON on a config type emitting invalid JSON (e.g. bare NaN/Infinity via hand-rolled marshaling); memory corruption. Plain encoding/json cannot produce this.","commonSituations":"Contributors adding custom marshalers to config types.","solutions":["Report upstream as a bug with the config contents; there is no user-level remediation","If you added a custom MarshalJSON, make it emit strict RFC 8259 JSON (no NaN/Infinity) and round-trip test it"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"if err := saveValidatedConfig(cfg); err != nil {\n\tif strings.Contains(err.Error(), \"failed to decode serialized config\") {\n\t\t// invariant break inside picoclaw itself — collect a bug report\n\t\t// with the config contents; no caller-side remediation exists\n\t\treturn fmt.Errorf(\"internal picoclaw bug (config round-trip): %w\", err)\n\t}\n\treturn err\n}","preventionTips":["If you maintain a fork, round-trip test any custom MarshalJSON implementations","Treat this message as 'report upstream', not as a config problem"],"tags":["go","json","internal","invariant"],"backgroundTag":null,"analyzedSha":"49183d7e8daed0dba89ddbb6fcb60089401d9680","analyzedAt":"2026-08-15T21:55:41.315Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}