derailed/k9s · warning

k9s config file %q load failed: %w

Error message

k9s config file %q load failed:
%w

What it means

Returned from Config.Load (internal/config/config.go:283) when the main k9s config file fails validation against the K9s JSON schema (data.JSONValidator.Validate with json.K9sSchema). Typically means unknown keys, misspelled keys, or values that changed shape between k9s versions. Errors are joined (errors.Join) — the schema error may arrive together with the unmarshal error from line 288 — and notably Load still merges the parsed config before returning, so the error is advisory: partial config is in effect.

Source

Thrown at internal/config/config.go:283

func (c *Config) Merge(c1 *Config) {
	c.K9s.Merge(c1.K9s)
}

// Load loads K9s configuration from file.
func (c *Config) Load(path string, force bool) error {
	if _, err := os.Stat(path); errors.Is(err, fs.ErrNotExist) {
		if err := c.Save(force); err != nil {
			return err
		}
	}
	bb, err := os.ReadFile(path)
	if err != nil {
		return err
	}
	var errs error
	if err := data.JSONValidator.Validate(json.K9sSchema, bb); err != nil {
		errs = errors.Join(errs, fmt.Errorf("k9s config file %q load failed:\n%w", path, err))
	}

	var cfg Config
	if err := yaml.Unmarshal(bb, &cfg); err != nil {
		errs = errors.Join(errs, fmt.Errorf("main config.yaml load failed: %w", err))
	}
	c.Merge(&cfg)

	return errs
}

// Save configuration to disk.
func (c *Config) Save(force bool) error {
	contextName := c.K9s.ActiveContextName()
	// Skip saving if no context is configured
	if contextName == "" {
		slog.Debug("No context configured, skipping config save")
		return nil

View on GitHub (pinned to 2d3ccc6ba2)

Solutions

  1. Read the validator detail in the message — it names the offending key/field and the schema path
  2. Rename or delete the flagged keys per the current version's config schema
  3. After a version upgrade, back up and let k9s regenerate a fresh config, then re-apply your customizations
  4. Keep one k9s version across machines if you sync the config file

Example fix

# before: config.yml after upgrade
ui:
  skin: monokai      # removed key in new schema -> validation error

# after: check schema, use current key
ui:
  skin: monokai
  # e.g. renamed to: activeSkin: monokai  (per validator message)
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-validate the config against the shipped schema before k9s loads it:
func configSchemaOK(path string) bool {
	bb, err := os.ReadFile(path)
	if err != nil {
		return false
	}
	return data.JSONValidator.Validate(json.K9sSchema, bb) == nil
}

Try / catch

if err := cfg.Load(path, force); err != nil {
	// Load joins schema + unmarshal errors; split them:
	var joined interface{ Unwrap() []error }
	if errors.As(err, &joined) {
		for _, e := range joined.Unwrap() {
			if strings.Contains(e.Error(), "load failed") {
				// schema/yaml drift: warn, config still partially applied
			} else {
				// harder failure: inspect
			}
		}
	}
}

Prevention

When it happens

Trigger: Upgrading k9s while the old config.yml contains keys removed from the new schema (or vice versa: a newer config opened by an older k9s); hand-editing with typo'd key names like 'refreshRate' vs 'refreshrate'; structurally valid YAML that violates the schema.

Common situations: k9s major-version upgrades; dotfiles synced across machines running different k9s versions; copy-pasted config snippets from blog posts targeting a different version.

Related errors


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