Skip to content

bug: : emit warning when loadGazeConfigBestEffort silently rejects invalid config #155

Description

@yvonnedevlinrh

Summary

loadGazeConfigBestEffort silently falls back to DefaultConfig() whenconfig.Load returns a validation error, producing no warning on stderr.
After PR #154 added threshold validation to config.Load, users with invalid .gaze.yaml thresholds now get clear errors from CLI commands (gaze analyze, gaze quality, gaze docscan) but silent default substitution from gaze crap and gaze report.

Reproduction

Given a .gaze.yaml with an out-of-range threshold:

classification:
  thresholds:
    contractual: 500
    incidental: 50
# CLI commands: clear error (correct)
$ gaze quality .
Error: loading config: classification.thresholds.contractual must be in [1, 99], got 500

# Best-effort callers: silent fallback to defaults (no warning)
$ gaze crap .
# Runs successfully using contractual=80, incidental=50 (defaults)
# No indication that the user's thresholds were rejected

$ gaze report --format=json .
# Same - silently uses defaults

Expected vs Actual

  • Expected: gaze crap and gaze report should emit a stderr warning when config.Load rejects the user's .gaze.yaml, so the user knows their thresholds are being replaced with defaults.
  • Actual: The commands run silently with default thresholds. The user's invalid config is ignored with no feedback.

Root cause

Both copies of loadGazeConfigBestEffort discard the error from config.Load without logging:

if err != nil {
    return config.DefaultConfig() // silent - no warning emitted
}

This was harmless before PR #154 because config.Load never rejected threshold values. Now that it validates thresholds, the silent fallback can mask configuration problems from users.

Suggested fix

Add a stderr warning when config.Load returns an error, before falling
back to defaults:

if err != nil {
    fmt.Fprintf(os.Stderr, "warning: %v; using default configuration\n", err)
    return config.DefaultConfig()
}

Apply to both copies:

  • internal/aireport/runner_steps.go (loadGazeConfigBestEffort)
  • internal/crap/contract.go (loadGazeConfigBestEffort)

A follow-up consolidation of the two identical loadGazeConfigBestEffort functions into a shared helper (see #139) would prevent this kind of divergence in the future.

Files to modify

  • internal/aireport/runner_steps.go - add stderr warning in loadGazeConfigBestEffort
  • internal/crap/contract.go - add stderr warning in loadGazeConfigBestEffort

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    Status
    No status

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions