sipeed/picoclaw · error
failed to parse legacy skills security config: %w
Error message
failed to parse legacy skills security config: %w
What it means
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.
Source
Thrown at pkg/config/security.go:81
content := rootNode.Content[0].Content
for i := 0; i < len(content); i += 2 {
if i+1 < len(content) {
key := content[i].Value
if key == "channels" || key == "channel_list" {
channelsNode = content[i+1]
break
}
}
}
}
// Unmarshal non-channel fields from security.yml
// This will resolve encrypted values for model_list, tools, etc.
if err := yaml.Unmarshal(data, cfg); err != nil {
return fmt.Errorf("failed to parse security config %s: %w", securityPath, err)
}
if err := applyLegacySkillsSecurityConfig(cfg, data); err != nil {
return fmt.Errorf("failed to parse legacy skills security config: %w", err)
}
// Restore channels from saved, then manually merge from security.yml
cfg.Channels = make(ChannelsConfig)
for name, savedBC := range savedChannels {
cfg.Channels[name] = savedBC
}
// If we found a channels node in security.yml, merge it into existing channels
if channelsNode != nil {
if err := cfg.Channels.UnmarshalYAML(channelsNode); err != nil {
return fmt.Errorf("failed to merge channels from security config: %w", err)
}
}
return nil
}
View on GitHub (pinned to 49183d7e8d)
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
Defensive patterns
Strategy: try-catch
Validate before calling
// Detect legacy skills blocks before load and migrate them explicitly. var root yaml.Node _ = yaml.Unmarshal(data, &root) // walk root for legacy skills keys; if present, run the migration tool first
Try / catch
if err := loadSecurityConfig(cfg, p); err != nil {
if strings.Contains(err.Error(), "legacy skills") {
// point user at migration command instead of raw failure
}
return err
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- model_name must be a string, got %T
- model_name is required: %#v
- failed to parse security config %s: %w
- failed to parse security config: %w
- failed to merge channels from security config: %w
AI-assisted analysis of sipeed/picoclaw@49183d7e8d (2026-08-15).
Data as JSON: /api/errors/499a3a3c8bcbde03.
Report an issue: GitHub.