{"record":{"id":"499a3a3c8bcbde03","repo":"sipeed/picoclaw","slug":"failed-to-parse-legacy-skills-security-config-w","errorCode":null,"errorMessage":"failed to parse legacy skills security config: %w","messagePattern":"failed to parse legacy skills security config: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/config/security.go","lineNumber":81,"sourceCode":"\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\n\treturn nil\n}\n","sourceCodeStart":63,"sourceCodeEnd":99,"githubUrl":"https://github.com/sipeed/picoclaw/blob/49183d7e8daed0dba89ddbb6fcb60089401d9680/pkg/config/security.go#L63-L99","documentation":"Returned by loadSecurityConfig when applyLegacySkillsSecurityConfig fails. That helper re-parses security.yml into a yaml.Node and applies the legacy skills security section (old layout where skills security lived under a different key shape). It errors if its own node unmarshal fails or if the legacy skills node has an invalid structure the legacy applier cannot process.","triggerScenarios":"security.yml contains a legacy-format `skills:` security block whose value does not match the shape applyLegacySkillsSecurityConfig expects (wrong nesting, wrong element types), or the second node parse fails on content the first parse tolerated. The underlying error is wrapped verbatim.","commonSituations":"Upgrading from an older release that wrote the legacy skills-security layout while keeping the old security.yml; partially migrated files that contain both new and legacy keys; hand-merged configs where the skills section got mangled.","solutions":["Inspect the skills-related section of security.yml against the legacy format expected by your previous version; the wrapped error identifies the failing piece","Remove the stale legacy skills block and express the same settings in the current format, then reload","Re-generate security.yml with the current version so legacy blocks are rewritten in the new schema","If you must keep the legacy block, fix its structure so each entry matches the legacy applier's expected map shape"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Detect legacy skills blocks before load and migrate them explicitly.\nvar root yaml.Node\n_ = yaml.Unmarshal(data, &root)\n// walk root for legacy skills keys; if present, run the migration tool first","typeGuard":null,"tryCatchPattern":"if err := loadSecurityConfig(cfg, p); err != nil {\n\tif strings.Contains(err.Error(), \"legacy skills\") {\n\t\t// point user at migration command instead of raw failure\n\t}\n\treturn err\n}","preventionTips":["Run the provided config-migration step on every upgrade before first boot","Delete legacy skills sections once migrated; don't keep both layouts","Back up security.yml before version upgrades"],"tags":["go","config","yaml","skills","legacy","migration"],"backgroundTag":null,"analyzedSha":"49183d7e8daed0dba89ddbb6fcb60089401d9680","analyzedAt":"2026-08-15T21:55:41.315Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}