Consider an empty input, a constant filter and --exit-status. The result is an empty output and the exit code is 0:
$ jq --exit-status 'false' /dev/null
$ echo $?
0
The manual suggests that the exit code should be 4 here:
-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.
Should the program be changed to match the manual, or should the manual be updated?
When you write “echo ‘’”, jq sees an empty stream. So ‘. = “hey”’ evaluates to the empty stream, which is not a JSON entity.
Then perhaps jq should exit with error code 4?
-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.
An exit code of 4 generally indicates an error, but to jq's reasoning,
having no JSON entities in the input stream is not indicative of an error.
If you need that behavior, you should pass the -e flag.
On Tue, Oct 10, 2017 at 4:12 AM Hoàng Xuân Phú notifications@github.com
wrote:
Then perhaps jq should exit with error code 4?
-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.—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
https://github.com/stedolan/jq/issues/1497#issuecomment-335395588, or mute
the thread
https://github.com/notifications/unsubscribe-auth/ADQ4Vy9159C17EkZ9aA7cfY52md2qoXvks5sqybQgaJpZM4PzaXF
.
@phunehehe - You're right that the documentation is inconsistent with the actual behavior, but I think you'll find that the jq maintainers would prefer to change the former rather than adjusting the latter solely for the sake of conformance with the documentation.
Do you think that -e in conjunction with the "no values" case should result in a distinct error code?
I only think the documentation and the actual behavior should be consistent. Either way seems okay.
Rereading my original issue comment I find it lengthy and somewhat misleading, so I have updated it to clarify.
Workaround: jq -ne 'inputs | ...'.
FWIW, I don't think this is a bug. No inputs -> not jq's problem.
I'll sleep on this. For now I think this is just the docs being incomplete.
I'm finding this confusing as well. My use case is that I have a command that outputs JSON (it's supposed to anyway!) and I want to test whether its output was a true value or not. It works fine until that command generates no output at all (simulated with echo | below), perhaps because the input command itself had some error.
# This works as expected
⟫ echo true | jq --exit-status '. == true' >/dev/null && echo "Input was true"
Input was true
# This works as expected
⟫ echo false | jq --exit-status '. == true' >/dev/null && echo "Input was true"
# This case is confusing/misleading
⟫ echo | jq --exit-status '. == true' >/dev/null && echo "Input was true"
Input was true
It seems like jq --exit-status should exit with some error code (4 would be fine, or whatever you like) so that one can distinguish between an actual true result and an [error condition?] where no valid result was ever produced.
Is there some other way to detect that the input was empty/invalid with a single pipeline?
I tried using the Alternative operator - // but I must be misunderstanding something because it just seems to ignore my entire expression when the input is [invalid?].
⟫ echo | jq --exit-status '( . // false ) == true' >/dev/null && echo "Input was true"
Input was true
If it truly considers that input invalid, then it should at least give an error instead of silently failing.
But if it considers it as null (I wish it did; could we add a --invalid-input-as-null option?), then everything could work nicely:
⟫ jq -n '. // false'
false
# Why does this behave so differently?
⟫ echo | jq '. // false'
By the way, it looks like there was an earlier issue for this at #1142.
Workaround:
jq -ne 'inputs | ...'.
Fine for simple cases, but not practical when you need to pipe in from another program.
Anyway, "workaround" implies that there is a problem needing to be worked around ;)
FWIW, I don't think this is a bug. No inputs -> not jq's problem.
So the filter gets run once for each JSON value in the input, so if there's 0 inputs it means the filter doesn't even get run at all (0 times)... Is that what you mean? Is that how it works?
I think I'm slowly but finally understanding that part now, which would explain why jq outputs absolutely nothing, even when I try to provide a fallback like '. // false'.
Sure, it's not _necessarily_ jq's problem, but jq could be made more useful, flexible, and friendly ... :)
What bugs me the most is that you can't even write a jq filter that works properly for the "no input" case because your filter apparently doesn't even get run in that case...
I can see how this shouldn't necessarily be an error if not using --exit-status...
But I still can't figure out how this can be considered useful or correct behavior to have jq --exit-status silently return 0 when there are no JSON values in the input.
The definition of --exit-status is defined in terms of the "last output value": false or null => 1, any other value => 0.
But when the input is empty, there is _no_ output value — in other words, not sufficient data to determine whether the output value is some value or another value.
Since we depend upon an output value in order to determine the exit code (in the case of --exit-status at least), we should fail if this dependency can't be satisfied.
This appears to have been the intent, too, since the docs clearly state "4 if no valid result was ever produced".
I think it is fair to say that no result was ever produced in this case. (In what other case could that even be said??)
(I'm not sure _exactly_ how "result" is defined, but I see the term also used in https://stedolan.github.io/jq/manual/#empty
emptyreturns no results. None at all. Not evennull.
)
Since no result was produced, it must exit with 4.
Since the filter apparently doesn't even get run (I'm finally learning) when there are 0 input values, and we therefore have no other means by which to influence the output value, it seems only fair that jq itself should report the lack of output value somehow. And what better way than with a unique exit code (in case the calling script actually wanted to distinguish between this case and the the case where the output value was false or null (exit 1))!
Ah I didn't see https://github.com/stedolan/jq/issues/1142 before. I'm closing this one as a duplicate then.
Most helpful comment
Workaround:
jq -ne 'inputs | ...'.FWIW, I don't think this is a bug. No inputs -> not jq's problem.