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

  1. Inspect the skills-related section of security.yml against the legacy format expected by your previous version; the wrapped error identifies the failing piece
  2. Remove the stale legacy skills block and express the same settings in the current format, then reload
  3. Re-generate security.yml with the current version so legacy blocks are rewritten in the new schema
  4. 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

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

Related errors


AI-assisted analysis of sipeed/picoclaw@49183d7e8d (2026-08-15). Data as JSON: /api/errors/499a3a3c8bcbde03. Report an issue: GitHub.