By default jq exits 0 whenever it parsed the input and ran the filter, regardless of the result, so 'jq ".enabled" config.json' succeeds whether the value is true, false, or absent. Using jq as a test in a shell script needs '-e'.
With '-e', the exit status is 0 if the last output value was neither false nor null, 1 if it was false or null, and 4 if no valid result was ever produced, which is what happens when the filter selects nothing. That three-way distinction is the point: 'jq -e ".items[] | select(.id == 7)"' exits 4 when there is no such item and 0 when there is, so a script can tell absence from a falsy value.
A parse error or a filter runtime error exits 2 or 5 respectively, so a bare 'if jq -e ...' treats malformed input as a false result unless you check the code explicitly. Combine with '--exit-status' and an explicit rc check for anything important. Note that '-e' looks only at the last value, so a filter producing several outputs is judged by the final one.