sipeed/picoclaw · error
failed to parse security config: %w
Error message
failed to parse security config: %w
What it means
Returned by loadSecurityConfig when the first yaml.Unmarshal of security.yml into a yaml.Node fails — i.e. the file is not syntactically valid YAML at all. The node parse is a pure syntax check before any typed decoding happens, so this error means broken YAML structure: tab indentation, unbalanced quotes/brackets, bad anchors/aliases.
Source
Thrown at pkg/config/security.go:57
data, err := os.ReadFile(securityPath)
if err != nil {
if os.IsNotExist(err) {
return nil
}
return fmt.Errorf("failed to read security config: %w", err)
}
// Save existing channels and ModelList before unmarshal
savedChannels := make(ChannelsConfig, len(cfg.Channels))
for name, bc := range cfg.Channels {
savedChannels[name] = bc
}
// savedModelList := cfg.ModelList
// Parse YAML into a yaml.Node tree to extract channels node
var rootNode yaml.Node
if err := yaml.Unmarshal(data, &rootNode); err != nil {
return fmt.Errorf("failed to parse security config: %w", err)
}
// Extract channels node (support both 'channels' and 'channel_list' keys)
var channelsNode *yaml.Node
if len(rootNode.Content) > 0 {
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.ymlView on GitHub (pinned to 49183d7e8d)
Solutions
- Run a YAML lint/parse check on the file: `yamllint security.yml` or `python -c "import yaml,sys;yaml.safe_load(open('security.yml'))"` to get the exact line/column
- Replace tabs with spaces for indentation and fix the reported construct (quote, bracket, alias)
- Restore from a backup or re-generate security.yml via the app's save/rotate path if hand-repair is impractical
- Re-run the config load to confirm the parse succeeds
Example fix
# before (tab indentation) model_list: - model_name: gpt-4o # after (spaces) model_list: - model_name: gpt-4o
Defensive patterns
Strategy: validation
Validate before calling
// Syntax-check security.yml before app startup.
func yamlSyntaxOK(path string) error {
data, err := os.ReadFile(path)
if err != nil { return err }
var node yaml.Node
return yaml.Unmarshal(data, &node)
} Try / catch
if err := loadSecurityConfig(cfg, p); err != nil {
var yamlErr *yaml.TypeError
if errors.As(err, &yamlErr) {
// decode error: fix schema in file
}
return err // syntax errors surface as wrapped yaml errors; show file+line
} Prevention
- Configure editors to use spaces, never tabs, for YAML
- Run yamllint on security.yml in CI
- Prefer the app's own save path over hand-editing so files stay well-formed
When it happens
Trigger: security.yml contains a tab character used for indentation, an unclosed quote or bracket, an undefined YAML alias (`*foo` with no `&foo`), or duplicate keys that the parser rejects. Any of these make yaml.Unmarshal(data, &rootNode) return a syntax error which is wrapped here.
Common situations: Hand-editing security.yml in an editor that inserts tabs, pasting YAML from a website/chat that mangles indentation, or truncated files after a crash mid-write. Because the file is written atomically by saveSecurityConfig, corruption almost always comes from manual edits or external tooling.
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 legacy skills 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/4b39689ec4fdf592.
Report an issue: GitHub.