{"record":{"id":"2e892c25cfeb6e2c","repo":"sipeed/picoclaw","slug":"failed-to-marshal-security-config-w","errorCode":null,"errorMessage":"failed to marshal security config: %w","messagePattern":"failed to marshal security config: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/config/security.go","lineNumber":200,"sourceCode":"\t\tfor key, value := range legacyRegistry.Param {\n\t\t\tif _, exists := registryCfg.Param[key]; !exists {\n\t\t\t\tregistryCfg.Param[key] = value\n\t\t\t}\n\t\t}\n\t\tcfg.Tools.Skills.Registries.Set(name, registryCfg)\n\t}\n\n\treturn nil\n}\n\n// saveSecurityConfig saves the security configuration to security.yml\nfunc saveSecurityConfig(securityPath string, sec *Config) error {\n\tvar buf bytes.Buffer\n\tenc := yaml.NewEncoder(&buf)\n\tenc.SetIndent(2)\n\terr := enc.Encode(sec)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to marshal security config: %w\", err)\n\t}\n\treturn fileutil.WriteFileAtomic(securityPath, buf.Bytes(), 0o600)\n}\n\n// SensitiveDataCache caches the strings.Replacer for filtering sensitive data.\n// Computed once on first access via sync.Once.\ntype SensitiveDataCache struct {\n\treplacer *strings.Replacer\n\tonce     sync.Once\n}\n\n// SensitiveDataReplacer returns the strings.Replacer for filtering sensitive data.\n// It is computed once on first access via sync.Once.\nfunc (sec *Config) SensitiveDataReplacer() *strings.Replacer {\n\tsec.initSensitiveCache()\n\treturn sec.sensitiveCache.replacer\n}\n","sourceCodeStart":182,"sourceCodeEnd":218,"githubUrl":"https://github.com/sipeed/picoclaw/blob/49183d7e8daed0dba89ddbb6fcb60089401d9680/pkg/config/security.go#L182-L218","documentation":"Returned by saveSecurityConfig when yaml.Encoder fails to serialize the Config being written to security.yml. Encoding errors mean some value in the in-memory Config cannot be represented as YAML: a field whose custom MarshalYAML returns an error, a map key type the encoder rejects, or values like NaN that YAML cannot serialize. The write is aborted before WriteFileAtomic, so the existing file on disk is untouched.","triggerScenarios":"Calling the save path (config rotation, credential update) while Config holds an unmarshalable value — e.g. a Channels entry or model_list element of a type whose marshaler errors, a map with non-string keys injected programmatically, or float NaN in a numeric field. enc.Encode(sec) returns the marshal error and it is wrapped here.","commonSituations":"Programmatic mutation of Config before save (plugins/tests inserting odd types), version changes that added a field with a buggy custom marshaler, or secrets containing values that fail a strict marshaler. Because the write is atomic, callers see the old security.yml preserved and only the error to diagnose.","solutions":["Log the wrapped error — the yaml encoder names the value/type it failed on; fix or remove that value before saving","If you built/modified Config in code, sanitize untrusted fields (drop unknown types, replace NaN with a valid number) before invoking save","Reproduce with a minimal Config to isolate which field fails marshal, then correct its type","Report/patch the custom MarshalYAML involved if a legit value cannot round-trip"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Dry-run marshal before saving to catch unserializable values.\nfunc canMarshal(v any) error {\n\tenc := yaml.NewEncoder(io.Discard)\n\tdefer enc.Close()\n\treturn enc.Encode(v)\n}","typeGuard":null,"tryCatchPattern":"if err := saveSecurityConfig(path, sec); err != nil {\n\t// existing file is untouched (atomic write) — safe to log, fix Config, retry\n\tlog.Printf(\"security save failed (file unchanged): %v\", err)\n\treturn err\n}","preventionTips":["Don't inject arbitrary Go types into Config before save; normalize to schema types","Unit-test round-trip (save->load) of Config in CI to catch marshaler regressions","Remember the write is atomic: on error the old security.yml is preserved, so retry after fixing"],"tags":["go","config","yaml","serialization","security"],"backgroundTag":null,"analyzedSha":"49183d7e8daed0dba89ddbb6fcb60089401d9680","analyzedAt":"2026-08-15T21:55:41.315Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}