Skip to content

fix(yaml): stop retrying an unrecoverable decode error in condition - #10238

Merged
olblak merged 2 commits into
updatecli:mainfrom
loispostula:fix/yaml-condition-decode-loop
Sep 4, 2026
Merged

olblak merged 2 commits into
updatecli:mainfrom
loispostula:fix/yaml-condition-decode-loop

Conversation

@loispostula

Copy link
Copy Markdown
Contributor

The yamlpath engine retries a decode error it cannot recover from, so a single
unparseable file makes Condition allocate until the process is OOM-killed.

yaml.v3 does not advance past a syntax error: once Decode fails, every
subsequent call returns the same non-EOF error. The loop appends an error and
continues, so it spins forever:

if derr := dec.Decode(&doc); derr != nil {
    if derr == io.EOF { break }
    errorMessages = append(errorMessages, fmt.Errorf(
        "%q - parsing yaml file: %w", originalFilePath, err))
    continue
}

A heap profile of an org-wide GitHub Action autodiscovery run (45 repositories
via a githubsearch scm) shows where it goes:

Showing nodes accounting for 14.62GB, 99.35% of 14.71GB total
      flat  flat%   sum%        cum   cum%
   11.16GB 75.83% 75.83%    11.22GB 76.29%  fmt.errorf
    2.49GB 16.93% 92.76%    14.69GB 99.81%  ...resources/yaml.(*Yaml).Condition

    1.80GB    12.67GB    111:  errorMessages = append(errorMessages, fmt.Errorf(

The trigger in our case was a Markdown file sitting in a .github/workflows
directory. Its first document parses as a scalar; the remainder then yields a
sticky yaml: line 8: did not find expected <document start>. Any file that
parses partially will do it.

This stops reading the file on such an error, which is what source.go and
target_yamlpath.go already do for the same case — condition.go was the only
one retrying. It also wraps derr rather than err, which is nil at that
point, so the message reported %!w(<nil>) instead of the parse failure.

Test

cd pkg/plugins/resources/yaml
go test

Test_Condition_yamlpathUndecodableFile fails (10s guard, "the decoder loop is
spinning on a non-EOF error") with continue restored, and passes with break.

Verified against the real workload that surfaced it — same policy set, same 45
repositories: 15.4 GB peak, dying after 13 repositories → 886 MB peak across
547 pipelines
.

Additional Information

Checklist

  • I have updated the documentation via pull request in website repository.
  • I have tested this pull request manually with a custom Updatecli build and it works as expected.

Tradeoff

Stopping at the first undecodable document means later documents in that file
are not inspected. They are unreachable anyway: the decoder cannot get past the
syntax error, so the previous behaviour never reached them either — it just
spun. The condition still reports the file as failing.

Potential improvement

derr == io.EOF could be errors.Is(derr, io.EOF) here and in the two sibling
files. Left alone to keep this diff to the bug.

yaml.v3 does not advance past a syntax error, so a file whose first document
parses and whose remainder does not makes Decode return the same non-EOF error
on every call. The yamlpath engine appended an error and continued, spinning
until the process was OOM-killed.

A heap profile of an org-wide autodiscovery run showed 11.16GB of 14.71GB held
in fmt.Errorf under (*Yaml).Condition. The trigger was a Markdown file sitting
in a .github/workflows directory: its first document parses as a scalar, the
rest yields a sticky "did not find expected <document start>".

Stop reading the file instead, which is what source.go and target_yamlpath.go
already do for the same error. Also wrap derr rather than err, which was nil at
that point and hid the real cause.

Signed-off-by: Loïs Postula <lois@mbrella.eu>
@olblak
olblak enabled auto-merge (squash) September 4, 2026 11:09
@olblak
olblak merged commit 93919b1 into updatecli:main Sep 4, 2026
8 checks passed
@olblak olblak added bug Something isn't working resource-yaml Resource of kind YAML labels Sep 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working resource-yaml Resource of kind YAML

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants