Skip to content

jq: a ?-wrapped generator piped from .. in path mode resumes after the error, so its side effects over-fire #2909

Description

@newhoggy

Severity: Low (side-effect count; output matches)

Summary

In path mode only, and only when the ?-wrapped generator is reached through .., an error
inside the generator does not backtrack out of the enclosing .[] — evaluation resumes with
the next element, so a side effect ahead of the error fires once per element instead of once.

Repro

Confirmed live against jq 1.7.1 and succinctly at a953112f2; pre-existing (the same
divergence reproduces on 1b12aa528, before #2694's streaming work, so it is not caused by it):

$ echo '[true,false]' | jq -c '[path(.. | (.[]|stderr|.+0)?)]'
true[]

$ echo '[true,false]' | succinctly jq -c '[path(.. | (.[]|stderr|.+0)?)]'
truefalse[]

.+0 on a boolean raises; jq's try aborts the whole body, so .[] is never resumed and
stderr writes once. Here .[] continues to the second element and writes twice.

Three neighbouring spellings all agree with jq, which is what localises it to the
..-piped path-mode route rather than to ? or to .[]:

$ echo '[true,false]' | jq -c '[(.[]|stderr|.+0)?]'            # true[]   — both agree
$ echo '[true,false]' | jq -c '[.. | (.[]|stderr|.+0)?]'       # true[]   — both agree (value mode)
$ echo '[true,false]' | jq -c '[path((.[]|stderr|.+0)?)]'      # true[]   — both agree

So the difference appears only when the ? sits downstream of .. and inside path().
Likely the node .. delivers is not the document's own tracked value, routing the ? through
a different arm than the standalone path((...)?) spelling takes
(resolve_optional_sink vs. whatever the piped stage reaches).

Fix direction

Find which arm the .. | stage routes the Optional through and make its error handling stop
the enclosing generator, as resolve_optional_sink already does for the standalone spelling.
Needs a live-oracle differential sweep against jq 1.7.1 per ADR-0018 before landing; the
neighbouring rows above are the regression guards.

Activity

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

    OpusSuitable for an Opus-class model to implementTriagedIssue has been read, planned, and its model-class label verified

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions