Skip to content

fix: scope mixin fallback to affected candidate chain only #507

Description

@yuanchen8911

Summary

When a mixin constraint fails in evaluateMixinConstraints, the current behavior resets the entire recipe to base-only output — all non-base overlays are excluded, including unrelated overlays (e.g., monitoring-hpa) that had nothing to do with the failing mixin. ExcludedOverlays also over-reports by including ancestors in the exclusion list, contradicting the field contract.

Current Behavior

evaluateMixinConstraints (metadata_store.go:440-456) iterates all appliedOverlays and excludes every non-base entry:

for _, name := range *appliedOverlays {
    if name != baseRecipeName {
        *excludedOverlays = append(*excludedOverlays, name)
    }
}

This is intentionally conservative (documented in code comments as of PR #501), but has two problems:

  1. Unrelated overlays get excluded as collateral
  2. ExcludedOverlays includes ancestors, which should not appear per the field contract

Proposed Fix

  1. Scope the reset to only the candidate chain that declared the failing mixin, not all applied overlays
  2. Add exclusion reason to ExcludedOverlays (e.g., Reason: "mixin-constraint-failed" vs Reason: "constraint-failed") for debugging visibility
  3. Exclude only leaf overlays, not ancestors, from the exclusion list

Context

Identified during cross-review of PR #501. The all-or-nothing behavior is safe (returns more restrictive output, not less) but can confuse operators when unrelated components disappear from the recipe.

Related: #501

Metadata

Metadata

Assignees

Type

Fields

No fields configured for Bug.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions