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
- Read the wrapped yaml error line/column and fix the YAML syntax at that location.
- Compare against the expected schema: top-level 'rules:' with 'lowestEfficiencyThreshold', 'highestWastedBytes', 'highestUserWastedPercent' as scalar values.
- Validate the file with a YAML linter (yamllint) or 'yq .' before running dive.
- 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
- Template CI rule files from a single reviewed source instead of hand-editing.
- Keep threshold values as quoted strings matching the documented schema.
- Run yamllint/yq in CI before the dive step.
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
- unable to determine image source from %q: %v
- failed to read CI config file %s: %w
- no keybinding configured for '%s'
- failed to parse key %q: %w
- cannot export analysis: %w
AI-assisted analysis of wagoodman/dive@d6c691947f (2026-08-15).
Data as JSON: /api/errors/a683719631b4720b.
Report an issue: GitHub.