router-for-me/CLIProxyAPI · error

parse plugin enabled: %w

Error message

parse plugin enabled: %w

What it means

Thrown while decoding the 'enabled' field of a plugin instance in config.yaml. PluginInstanceConfig uses a custom UnmarshalYAML that walks the yaml.Node pair-by-pair; when the value under the 'enabled' key cannot be decoded into a Go bool, this wrapped error is returned. The %w chain carries the underlying gopkg.in/yaml.v3 type error (e.g. 'cannot unmarshal !!str into bool').

Source

Thrown at internal/config/config_types.go:67

		return nil
	}

	c.Raw = *deepCopyNode(value)
	if value.Kind != yaml.MappingNode {
		return nil
	}

	for i := 0; i+1 < len(value.Content); i += 2 {
		key := value.Content[i]
		node := value.Content[i+1]
		if key == nil {
			continue
		}
		switch key.Value {
		case "enabled":
			var enabled bool
			if errDecodeEnabled := node.Decode(&enabled); errDecodeEnabled != nil {
				return fmt.Errorf("parse plugin enabled: %w", errDecodeEnabled)
			}
			c.Enabled = &enabled
		case "priority":
			var priority int
			if errDecodePriority := node.Decode(&priority); errDecodePriority != nil {
				return fmt.Errorf("parse plugin priority: %w", errDecodePriority)
			}
			c.Priority = priority
		}
	}

	return nil
}

// MarshalYAML returns the preserved raw plugin YAML subtree for lossless config output.
func (c PluginInstanceConfig) MarshalYAML() (any, error) {
	if c.Raw.Kind == 0 {
		return defaultPluginInstanceConfigNode(), nil

View on GitHub (pinned to 78f0c4079e)

Solutions

  1. Open config.yaml, find the plugins section, and set enabled to a bare true or false (unquoted).
  2. Remove quotes around the value: change enabled: "true" to enabled: true.
  3. If the value was 'yes'/'no'/'on'/'off'/'1'/'0', replace it with true/false.
  4. Validate the file with a YAML parser or 'go run ./cmd/server --config config.yaml' before deploying.
  5. If you generate the config programmatically, ensure the field is emitted as a bool, not a string.

Example fix

# before (config.yaml)
plugins:
  configs:
    myplugin:
      enabled: "yes"

# after
plugins:
  configs:
    myplugin:
      enabled: true
Defensive patterns

Strategy: validation

Validate before calling

// Go: verify plugin enabled values are plain booleans before loading config.
import (
    "os"
    "gopkg.in/yaml.v3"
)

func pluginEnabledValid(path string) (bool, error) {
    data, err := os.ReadFile(path)
    if err != nil {
        return false, err
    }
    var root map[string]any
    if err := yaml.Unmarshal(data, &root); err != nil {
        return false, err
    }
    plugins, ok := root["plugins"].(map[string]any)
    if !ok {
        return true, nil // no plugins section
    }
    walkConfigs(plugins) // check every "enabled" under plugins.configs.*
    return true, nil
}

func walkConfigs(m map[string]any) {
    for _, v := range m {
        if inst, ok := v.(map[string]any); ok {
            if enabled, exists := inst["enabled"]; exists {
                if _, isBool := enabled.(bool); !isBool {
                    panic("plugin enabled must be a bare true/false")
                }
            }
        }
    }
}

Prevention

When it happens

Trigger: A plugins: section in config.yaml where a plugin instance sets enabled to a non-boolean, e.g. 'plugins:\n configs:\n myplugin:\n enabled: "yes"' or 'enabled: 1' or 'enabled: on/off' (YAML 1.2 core schema does not coerce these strings to bool). Also triggered by an empty scalar '~' or a nested map under 'enabled'.

Common situations: Copying a plugin block from documentation that used quoted strings; migrating from a config format that accepted 'yes'/'no'; editing config.yaml by hand while the file watcher hot-reloads a half-finished edit; using a YAML linter that auto-quotes booleans as strings.

Related errors


AI-assisted analysis of router-for-me/CLIProxyAPI@78f0c4079e (2026-08-15). Data as JSON: /api/errors/fcc98ed3dde1b250. Report an issue: GitHub.