{"record":{"id":"9a9358e70396b84c","repo":"sipeed/picoclaw","slug":"failed-to-parse-security-config-s-w","errorCode":null,"errorMessage":"failed to parse security config %s: %w","messagePattern":"failed to parse security config (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/config/security.go","lineNumber":78,"sourceCode":"\t// Extract channels node (support both 'channels' and 'channel_list' keys)\n\tvar channelsNode *yaml.Node\n\tif len(rootNode.Content) > 0 {\n\t\tcontent := rootNode.Content[0].Content\n\t\tfor i := 0; i < len(content); i += 2 {\n\t\t\tif i+1 < len(content) {\n\t\t\t\tkey := content[i].Value\n\t\t\t\tif key == \"channels\" || key == \"channel_list\" {\n\t\t\t\t\tchannelsNode = content[i+1]\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Unmarshal non-channel fields from security.yml\n\t// This will resolve encrypted values for model_list, tools, etc.\n\tif err := yaml.Unmarshal(data, cfg); err != nil {\n\t\treturn fmt.Errorf(\"failed to parse security config %s: %w\", securityPath, err)\n\t}\n\tif err := applyLegacySkillsSecurityConfig(cfg, data); err != nil {\n\t\treturn fmt.Errorf(\"failed to parse legacy skills security config: %w\", err)\n\t}\n\n\t// Restore channels from saved, then manually merge from security.yml\n\tcfg.Channels = make(ChannelsConfig)\n\tfor name, savedBC := range savedChannels {\n\t\tcfg.Channels[name] = savedBC\n\t}\n\n\t// If we found a channels node in security.yml, merge it into existing channels\n\tif channelsNode != nil {\n\t\tif err := cfg.Channels.UnmarshalYAML(channelsNode); err != nil {\n\t\t\treturn fmt.Errorf(\"failed to merge channels from security config: %w\", err)\n\t\t}\n\t}\n","sourceCodeStart":60,"sourceCodeEnd":96,"githubUrl":"https://github.com/sipeed/picoclaw/blob/49183d7e8daed0dba89ddbb6fcb60089401d9680/pkg/config/security.go#L60-L96","documentation":"Returned by loadSecurityConfig when the second yaml.Unmarshal — decoding security.yml directly into the Config struct — fails. The file is valid YAML as a node tree (that was checked first), but its contents do not fit the Config schema: wrong field types, custom UnmarshalYAML methods rejecting values, or duplicate/malformed keys. The message includes the security.yml path plus the wrapped decoder error with field context.","triggerScenarios":"A field that must be a scalar holds a map (e.g. `passphrase: {a: 1}`), a numeric field holds a non-number, or a nested type's custom UnmarshalYAML (e.g. ChannelsConfig, model_list entries) rejects a value. yaml.TypeError from the struct decode is wrapped into this message.","commonSituations":"Schema drift between an old security.yml and a new binary (fields changed shape across versions), hand-editing that moves a key one level up/down, or encrypted/legacy values placed under the wrong section. The specific field is named in the wrapped error text.","solutions":["Read the wrapped error: it names the failing field/type (e.g. `cannot unmarshal !!str into int`); fix that exact value in security.yml","Compare your security.yml keys against the current Config struct/version's documented schema — usually a version-upgrade mismatch","Re-generate security.yml with the current version (save/rotate flow) and re-apply only the values you need","If migrating from an older release, run the provided migration path instead of manually copying the old file"],"exampleFix":"# before\nprovider:\n  timeout: \"30s-not-a-number-field\"\n\n# after\nprovider:\n  timeout: 30","handlingStrategy":"validation","validationCode":"// Strict-type decode into the same Config before the real load.\nfunc strictCheck(data []byte, cfg *Config) error {\n\tdec := yaml.NewDecoder(bytes.NewReader(data))\n\tdec.KnownFields(true) // catch unknown keys too\n\tvar probe Config\n\treturn dec.Decode(&probe)\n}","typeGuard":null,"tryCatchPattern":"if err := loadSecurityConfig(cfg, p); err != nil {\n\tvar typeErr *yaml.TypeError\n\tif errors.As(err, &typeErr) {\n\t\tfor _, e := range typeErr.Errors { log.Printf(\"field error: %s\", e) }\n\t}\n\treturn err\n}","preventionTips":["Regenerate security.yml with the current version after upgrades instead of reusing old files","Diff schema docs between versions when bumping","Avoid moving keys between levels when hand-editing"],"tags":["go","config","yaml","schema","migration"],"backgroundTag":null,"analyzedSha":"49183d7e8daed0dba89ddbb6fcb60089401d9680","analyzedAt":"2026-08-15T21:55:41.315Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}