jq icon indicating copy to clipboard operation
jq copied to clipboard

jq shouldn't return 0 on an empty file with a nonexistent key

Open pwillis-els opened this issue 5 years ago • 11 comments

Describe the bug

When using jq to open an empty file, and a query of printing a particular key (which can't exist, because the file is empty), the return status is success (0). But it clearly didn't succeed in querying the key, because it didn't exist.

To Reproduce

vagrant@vagrant:~$ jq -r .foo /dev/null
vagrant@vagrant:~$ echo $?
0
vagrant@vagrant:~$ jq --version
jq-1.6

Expected behavior

Returns non-zero status.

Environment (please complete the following information):

  • OS and Version: Linux Ubuntu 18.04.3
  • jq version: 1.6

pwillis-els avatar Jan 10 '20 18:01 pwillis-els

You may be interested in the -e/--exit-status option.

Otherwise, this is the expected behaviour; jq successfully applied the filter to all zero inputs.

muhmuhten avatar Jan 12 '20 22:01 muhmuhten

hi, @pwillis-els
you may be interested in this doc. https://github.com/stedolan/jq/blob/master/docs/content/manual/manual.yml line:218

   * `-e` / `--exit-status`:
        Sets the exit status of jq to 0 if the last output values was
        neither `false` nor `null`, 1 if the last output value was
        either `false` or `null`, or 4 if no valid result was ever
        produced.  Normally jq exits with 2 if there was any usage
        problem or system error, 3 if there was a jq program compile
        error, or 0 if the jq program ran.
        Another way to set the exit status is with the `halt_error`
        builtin function.


test result

root@qq-001:test# ./jq/jq -r -e '.foo' /dev/null
root@qq-001:test# echo $?
4

Alanscut avatar Jan 13 '20 02:01 Alanscut

Huh, did not know about that option! Thanks, if this is expected behavior i'll close issue

pwillis-els avatar Jan 13 '20 05:01 pwillis-els

Re-opening this, I think there is still a case for some kind of error for this particular use case.

$ echo '[[{"name":"something","id":12345}]]' | jq -e -r '.[][] | [ .name, .id|tostring ] | join(",")'
something,12345
$ echo $?
0
$ echo '{"foo": "bar"}' | jq -e -r '.[][] | [ .name, .id|tostring ] | join(",")'
jq: error (at <stdin>:1): Cannot iterate over string ("bar")
$ echo $?
5
$ echo '[{}]' | jq -e -r '.[][] | [ .name, .id|tostring ] | join(",")'
$ echo $?
4
$ echo '' | jq -e -r '.[][] | [ .name, .id|tostring ] | join(",")'
$ echo $?
0

With -e option, failure to query the stream will return an error in different conditions. But if the stream is empty, it returns success.

This is a similar problem as noted in the following issue: https://github.com/stedolan/jq/issues/1142

Having to implement complicated workarounds every time you run jq, in the off-chance that the input was either a pipe or a file that was empty, just seems like poor design that could be fixed with a feature flag (that I would enable every single time I ran jq, and I wager most other people would as well).

pwillis-els avatar Jan 25 '20 23:01 pwillis-els

It could be that this is a problem with my version of jq?

$ jq --version
jq-1.6
$ jq -r -e '.foo' /dev/null
$ echo $?
0

pwillis-els avatar Jan 25 '20 23:01 pwillis-els

I would expect that at least the has() function would be able to catch this?

echo '' | jq -e 'has("foobar")'; echo $?
0

because clearly that is wrong?

It will fail on malformed json:

echo '123' | jq -e 'has("foobar")'; echo $?
jq: error (at <stdin>:1): Cannot check whether number has a string key
5

and also if the element is really not there:

echo '{}' | jq -e 'has("foobar")'; echo $?
false
1

lifeofguenter avatar Mar 24 '20 09:03 lifeofguenter

It was fixed via #1142 :

$ jq --version
jq-1.5-1-a5b5cbe

$ jq -e -r .foo /dev/null; echo $?
0

$ echo '' | jq -e '.foobar'; echo $?
0

$ echo '' | jq -e 'has("foobar")'; echo $?
0
$ ./jq --version
jq-1.6-129-g80052e5-dirty

$ ./jq -e -r .foo /dev/null; echo $?
4

$ echo '' | ./jq -e '.foobar'; echo $?
4

$ echo '' | ./jq -e 'has("foobar")'; echo $?
4

krayon avatar Mar 24 '21 01:03 krayon

This is still broken for me:

$ jq --version
jq-1.6
$ jq -e -r .foo /dev/null && echo "Exited OK"
Exited OK
$ echo '' | jq -e -r '.foobar' && echo "Exited OK"
Exited OK
$ echo '' | jq -e -r 'has("foobar")' && echo "Exited OK"
Exited OK

Omitting the -r argument does not change the outcome.

Has #1697 (the fix for #1142) not made its way to distros yet?

lytedev avatar Jul 07 '22 15:07 lytedev

Can't reproduce with master and seems the fixing is only in master yet https://github.com/stedolan/jq/commit/6d3d2750ec1e076cd86189b8fcfe1b760e2207c7

wader avatar Jul 07 '22 16:07 wader

There hasn't been a release since 2018, and #1697 was merged a month after that release.

muhmuhten avatar Jul 07 '22 16:07 muhmuhten

Ah that'll do it. Any reason jq hasn't released? Is everybody just all about gojq these days?

lytedev avatar Jul 22 '22 02:07 lytedev

jq 1.7 released with changed behaviour as requested. closing

emanuele6 avatar Sep 08 '23 20:09 emanuele6