Skip to content

kyaml merge2: $patch directives on list elements ignored with ListPrepend #6146

Description

@rm3l

/kind bug

Bug

When using merge2.MergeStrings with MergeOptions{ListIncreaseDirection: MergeOptionsListPrepend}, strategic merge patch directives ($patch: replace, $patch: delete) on individual associative list elements are silently ignored.

With default MergeOptions{} (Append), $patch: replace correctly replaces the matched list element. With ListPrepend, the original element remains unchanged and the replacement is dropped.

Root cause

In kyaml/yaml/walk/associative_sequence.go, setAssociativeSequenceElements() assembles the final list differently depending on the merge direction:

  • Append (correct): appendListNode(dest, itemsToBeAdded, ...); merged results from itemsToBeAdded overwrite originals in dest.
  • ListPrepend (buggy): appendListNode(itemsToBeAdded, dest, ...); the arguments are swapped for ordering, but this causes ElementSetter to overwrite already-merged items in itemsToBeAdded with the unmerged originals from dest, undoing $patch directive effects.

Reproduction

Minimal reproduction project: https://github.com/rm3l/kyaml-listprepend-bug

git clone https://github.com/rm3l/kyaml-listprepend-bug
cd kyaml-listprepend-bug
go test -v ./...
  • TestPatchReplaceWithDefaultMerge: PASS
  • TestPatchReplaceWithListPrepend: FAIL (the $patch: replace is ignored)

Versions affected

Tested and confirmed on:

  • sigs.k8s.io/kustomize/kyaml v0.18.1
  • sigs.k8s.io/kustomize/kyaml v0.19.0
  • sigs.k8s.io/kustomize/kyaml v0.21.0
  • sigs.k8s.io/kustomize/kyaml v0.21.1
  • Latest master commit (313aace, 2025-05-02)

Impact

This bug prevents combining ListPrepend (for controlling list item ordering) with $patch: replace or $patch: delete (for replacing/removing individual items by merge key). The two features are independent and should compose correctly IMHO.

Activity

  1. added
    needs-kindIndicates a PR lacks a `kind/foo` label and requires one.
    needs-triageIndicates an issue or PR lacks a `triage/foo` label and requires one.
    on May 12, 2026
  2. k8s-ci-robot commented on May 12, 2026

    @k8s-ci-robot
    Contributor

    This issue is currently awaiting triage.

    SIG CLI takes a lead on issue triage for this repo, but any Kubernetes member can accept issues by applying the triage/accepted label.

    The triage/accepted label can be added by org members by writing /triage accepted in a comment.

    Details

    Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

  3. changed the title [-]kyaml merge2: $patch directives on list elements ignored with ListPrepend[/-] [+]kyaml merge2: `$patch` directives on list elements ignored with `ListPrepend`[/+] on May 12, 2026
  4. rm3l commented on May 12, 2026

    @rm3l
    Author

    /kind bug

  5. added
    kind/bugCategorizes issue or PR as related to a bug.
    and removed
    needs-kindIndicates a PR lacks a `kind/foo` label and requires one.
    on May 12, 2026
  6. jang-hs commented on Sep 11, 2026

    @jang-hs

    This is not limited to direct kyaml users: api/filters/patchstrategicmerge merges with
    MergeOptionsListPrepend, so plain kustomize build hits it too. With this base and patch:

    # deployment.yaml (excerpt)
    containers:
    - name: nginx
      image: nginx:1.0
      env:
      - name: KEEP_ME
        value: "old"
    
    # patch.yaml (excerpt)
    containers:
    - name: nginx
      $patch: replace
      image: nginx:2.0

    kustomize v5.8.x emits the original container untouched — the patch is silently a no-op.
    #5255 looks like the same thing reported from the CLI side.

    /assign

  7. jang-hs commented on Sep 11, 2026

    @jang-hs

    Unassigning myself — @rm3l had #6147 open for this well before I picked it up, and I missed
    it. #6265 stays open in case the maintainers find it useful, but this one is not mine to hold.

    /unassign

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    kind/bugCategorizes issue or PR as related to a bug.needs-triageIndicates an issue or PR lacks a `triage/foo` label and requires one.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions