derailed/k9s · error

plugin unmarshal failed for %s: %w

Error message

plugin unmarshal failed for %s: %w

What it means

After schema validation succeeds for the single-plugin shape (json.PluginSchema), Plugins.load yaml.Unmarshals the bytes into the Plugin struct (internal/config/plugin.go:171-173). This error wraps a YAML decode/type failure specific to that struct.

Source

Thrown at internal/config/plugin.go:174

		return err
	}
	scheme, err := data.JSONValidator.ValidatePlugins(bb)
	if err != nil {
		slog.Warn("Plugin schema validation failed",
			slogs.Path, path,
			slogs.Error, err,
		)
		return fmt.Errorf("plugin validation failed for %s: %w", path, err)
	}

	d := yaml.NewDecoder(bytes.NewReader(bb))
	d.KnownFields(true)

	switch scheme {
	case json.PluginSchema:
		var o Plugin
		if err := yaml.Unmarshal(bb, &o); err != nil {
			return fmt.Errorf("plugin unmarshal failed for %s: %w", path, err)
		}
		if err := o.Validate(); err != nil {
			return fmt.Errorf("plugin validation failed for %s: %w", path, err)
		}
		p.Plugins[strings.TrimSuffix(filepath.Base(path), filepath.Ext(path))] = o
	case json.PluginsSchema:
		var oo Plugins
		if err := yaml.Unmarshal(bb, &oo); err != nil {
			return fmt.Errorf("plugin unmarshal failed for %s: %w", path, err)
		}
		for k := range oo.Plugins {
			plug := oo.Plugins[k]
			if err := plug.Validate(); err != nil {
				return fmt.Errorf("plugin %q validation failed for %s: %w", k, path, err)
			}
			p.Plugins[k] = plug
		}
	case json.PluginMultiSchema:

View on GitHub (pinned to 2d3ccc6ba2)

Solutions

  1. Run the file through a YAML linter (yamllint) or `python -c 'import yaml,sys; yaml.safe_load(open(sys.argv[1]))' file.yml`
  2. Fix indentation (spaces only), remove duplicate keys and smart quotes
  3. Simplify: remove anchors/merge keys and inline the values
  4. The wrapped error text names the YAML line/type at fault - read the %w tail
Defensive patterns

Strategy: validation

Validate before calling

// Strict-decode a plugin file the way k9s nearly does (decoder with KnownFields)
// to surface type/indent errors before launch.
func StrictLint(path string) error {
	b, _ := os.ReadFile(path)
	d := yaml.NewDecoder(bytes.NewReader(b))
	d.KnownFields(true)
	var o config.Plugin
	return d.Decode(&o)
}

Prevention

When it happens

Trigger: YAML that passes the JSON-schema check but still fails decoding into Plugin: duplicate YAML keys, tab indentation errors, unexpected anchors/aliases, or scalars that cannot coerce into the string/bool fields (e.g. `dangerous: yes-please`). Note this path uses yaml.Unmarshal (not the KnownFields decoder built at plugin.go:168-169), so unknown fields alone do not trigger it.

Common situations: Hand-edited plugin files with tabs instead of spaces; copy-paste from websites introducing smart quotes or duplicate keys; YAML anchors left over from templating.

Related errors


AI-assisted analysis of derailed/k9s@2d3ccc6ba2 (2026-08-15). Data as JSON: /api/errors/532375b58ae5b79d. Report an issue: GitHub.