wagoodman/dive · error

failed to unmarshal CI config file %s: %w

Error message

failed to unmarshal CI config file %s: %w

What it means

Thrown when yaml.Unmarshal of the CI rules file contents into the legacy rules wrapper struct fails. The file was read successfully but its YAML does not match the expected schema (a top-level 'rules' key with the three threshold string fields). The %w carries the go-yaml parse/type error with line information.

Source

Thrown at cmd/dive/cli/internal/options/ci.go:69

			// If we're hitting this case we should pretend that only the config file was provided and applied
			// on top of the default config values.
			yamlFile, err := os.ReadFile(c.ConfigPath)
			if err != nil {
				return fmt.Errorf("failed to read CI config file %s: %w", c.ConfigPath, err)
			}
			def := DefaultCIRules()
			r := legacyRuleFile{
				LowestEfficiencyThresholdString: def.LowestEfficiencyThresholdString,
				HighestWastedBytesString:        def.HighestWastedBytesString,
				HighestUserWastedPercentString:  def.HighestUserWastedPercentString,
			}
			wrapper := struct {
				Rules *legacyRuleFile `yaml:"rules"`
			}{
				Rules: &r,
			}
			if err := yaml.Unmarshal(yamlFile, &wrapper); err != nil {
				return fmt.Errorf("failed to unmarshal CI config file %s: %w", c.ConfigPath, err)
			}
			// TODO: should this be a deprecated use warning in the future?
			c.Rules = CIRules{
				LowestEfficiencyThresholdString: r.LowestEfficiencyThresholdString,
				HighestWastedBytesString:        r.HighestWastedBytesString,
				HighestUserWastedPercentString:  r.HighestUserWastedPercentString,
			}
		}
	}

	return nil
}

type legacyRuleFile struct {
	LowestEfficiencyThresholdString string `yaml:"lowestEfficiency"`
	HighestWastedBytesString        string `yaml:"highestWastedBytes"`
	HighestUserWastedPercentString  string `yaml:"highestUserWastedPercent"`
}

View on GitHub (pinned to d6c691947f)

Solutions

  1. Read the wrapped yaml error line/column and fix the YAML syntax at that location.
  2. Compare against the expected schema: top-level 'rules:' with 'lowestEfficiencyThreshold', 'highestWastedBytes', 'highestUserWastedPercent' as scalar values.
  3. Validate the file with a YAML linter (yamllint) or 'yq .' before running dive.
  4. Drop --ci-config to use DefaultCIRules() and re-add thresholds incrementally.

Example fix

# before (ci-rules.yaml)
rules:
  lowestEfficiencyThreshold:   # missing value -> unmarshal error

# after
rules:
  lowestEfficiencyThreshold: "0.9"
  highestWastedBytes: "50MB"
  highestUserWastedPercent: "0.6"
Defensive patterns

Strategy: validation

Validate before calling

# lint the CI rules file before dive runs
yamllint ci-rules.yaml || exit 1
yq '.rules | keys' ci-rules.yaml  # expect the three threshold keys

Prevention

When it happens

Trigger: Supplying --ci-config with a file that has YAML syntax errors (tabs, bad indentation) or semantically wrong types, e.g. rules.lowestEfficiencyThreshold given as a nested map or list instead of a string, or a completely different YAML document (a docker-compose file by mistake).

Common situations: Reusing an old dive config (dive.yaml) whose structure changed; hand-editing thresholds and breaking indentation; passing the application config file where a CI-rules-only file was expected; duplicate keys.

Related errors


AI-assisted analysis of wagoodman/dive@d6c691947f (2026-08-15). Data as JSON: /api/errors/a683719631b4720b. Report an issue: GitHub.