Skip to content

t2929: Fix config-helper.sh _jsonc_get discards false values#2934

Closed
marcusquinn wants to merge 1 commit intomainfrom
bugfix/config-helper-false-values
Closed

t2929: Fix config-helper.sh _jsonc_get discards false values#2934
marcusquinn wants to merge 1 commit intomainfrom
bugfix/config-helper-false-values

Conversation

@marcusquinn
Copy link
Owner

@marcusquinn marcusquinn commented Mar 5, 2026

Summary

  • Replace jq // empty alternative operator with explicit null checks in bash across 5 locations in config-helper.sh
  • false and 0 values are now correctly preserved instead of being silently discarded and replaced with defaults
  • Boolean configs (e.g., supervisor_pulse: false) can now be disabled via config.jsonc as intended

Root Cause

jq's // (alternative) operator treats both null and false as falsy. So false // empty returns empty, which becomes an empty string in bash, triggering the default fallback. This affected _jsonc_get, _jsonc_get_raw, cmd_list, and cmd_set.

Fix

Get the raw JSON value (without -r or // empty), check for literal "null" string in bash, then render with jq -r '.' only for non-null values. This correctly distinguishes null (key absent) from false/0 (key present with falsy value).

Verification

Tested all paths: _jsonc_get, _jsonc_get_raw, config_get, config_enabled, is_feature_enabled — all correctly return false for false values and fall through to defaults only for absent keys. ShellCheck clean (no new violations).

Closes #2929

Summary by CodeRabbit

  • Bug Fixes
    • Improved configuration value handling to correctly distinguish between absent settings and explicit falsy values (false, 0), enhancing reliability of configuration retrieval and defaults.

… empty

Replace jq's `// empty` alternative operator with explicit null checks in
bash. The `//` operator in jq treats both `null` and `false` as falsy,
so `false // empty` returns `empty` — silently discarding the value and
falling through to the default (typically `true`).

This made it impossible to disable any boolean config via config.jsonc.
The env var override path worked because it bypasses _jsonc_get entirely.

Fixed in 5 locations:
- _jsonc_get(): core getter used by config_get/config_enabled
- _jsonc_get_raw(): raw file getter
- cmd_list(): user override display (false showed as default)
- cmd_set(): default validation (false defaults rejected as unknown)
- cmd_list source detection: used -n on user_val instead of raw null check

Closes #2929
@gemini-code-assist
Copy link

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request addresses a critical bug where jq's alternative operator (//) incorrectly treated false and 0 as null, causing these valid configuration values to be ignored and replaced by default settings. The changes implement a more robust parsing mechanism by explicitly checking for null values in bash, ensuring that all intended boolean and numeric configurations are respected and applied correctly.

Highlights

  • Configuration Value Handling: Replaced jq's // empty operator with explicit null checks in bash across five locations in config-helper.sh.
  • Preservation of Falsy Values: false and 0 values are now correctly preserved in configurations instead of being silently discarded and replaced with defaults.
  • Boolean Configs: Boolean configurations, such as supervisor_pulse: false, can now be properly disabled via config.jsonc as intended.
Changelog
  • .agents/scripts/config-helper.sh
    • Modified _jsonc_get to explicitly check for null values in bash, preventing false and 0 from being discarded by jq's // empty operator.
    • Updated _jsonc_get_raw to handle null values explicitly in bash, ensuring false and 0 are not treated as empty.
    • Adjusted cmd_list to correctly retrieve user-defined false or 0 values by checking raw_user_val against null instead of relying on user_val being empty.
    • Modified cmd_set to validate config keys using the raw JSON value, allowing for proper distinction between null and false/0 when checking against defaults.
Activity
  • No human activity has been recorded on this pull request yet.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 5, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 50ccbb19-02ea-436c-b0c6-d910950b0faf

📥 Commits

Reviewing files that changed from the base of the PR and between 039d5c9 and ac5c63f.

📒 Files selected for processing (1)
  • .agents/scripts/config-helper.sh

Walkthrough

The script was updated to properly distinguish between absent JSON keys and explicit falsy values (false, 0). The jq // empty operator was replaced with explicit null checking using raw value variables, ensuring correct handling throughout the configuration hierarchy (env > user > defaults).

Changes

Cohort / File(s) Summary
Configuration Helper Null Handling
.agents/scripts/config-helper.sh
Refactored _jsonc_get, _jsonc_get_raw, cmd_list, and cmd_set functions to use explicit null checks via raw value variables instead of jq's // empty operator. Ensures falsy values (false, 0) are properly distinguished from absent keys, with added clarifying comments for null handling logic.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested labels

bug

Poem

Where null once hid in shadowed code,
Raw values now take lighter load,
False and zero stand their ground,
Config logic, clean and sound,
Zero debt—a DevOps crown! 👑✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 75.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly and specifically describes the main fix: addressing the bug where false values were being discarded in config-helper.sh's _jsonc_get function.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch bugfix/config-helper-false-values

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@marcusquinn
Copy link
Owner Author

Closing — this PR fixes the same bug as #2931 which was merged first. Issue #2929 is now resolved. PR #2934 has merge conflicts as a result of #2931 landing.

@marcusquinn marcusquinn closed this Mar 5, 2026
Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request correctly addresses a critical bug where false and 0 values in JSONC configuration were being discarded. The approach of fetching the raw value and explicitly checking for null in bash is robust and solves the problem effectively. My review includes a few suggestions to improve debuggability by removing stderr suppression, in line with the repository's general guidelines. Overall, this is a great fix.

# it treats `false` and `null` the same (both are falsy in jq). Instead,
# get the raw JSON value and check for null explicitly in bash.
local raw_value
raw_value=$(echo "$merged" | jq --arg p "$dotpath" 'getpath($p | split("."))' 2>/dev/null) || raw_value="null"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This correctly fixes the issue with false values. However, using 2>/dev/null suppresses potentially useful error messages from jq, for instance if the configuration file contains invalid JSON. This goes against a general rule for this repository. Since you're already handling the error case with || raw_value="null", you can safely remove the stderr redirection to improve debuggability.

Suggested change
raw_value=$(echo "$merged" | jq --arg p "$dotpath" 'getpath($p | split("."))' 2>/dev/null) || raw_value="null"
raw_value=$(echo "$merged" | jq --arg p "$dotpath" 'getpath($p | split("."))') || raw_value="null"
References
  1. In shell scripts with 'set -e' enabled, use '|| true' to prevent the script from exiting when a command like 'jq' fails on an optional lookup. Do not suppress stderr with '2>/dev/null' so that actual syntax or system errors remain visible for debugging.

echo "$json" | jq -r --arg p "$dotpath" 'getpath($p | split(".")) // empty' 2>/dev/null || echo ""
# Avoid `// empty` — it discards false and 0 (falsy in jq). Check for null explicitly.
local raw_value
raw_value=$(echo "$json" | jq --arg p "$dotpath" 'getpath($p | split("."))' 2>/dev/null) || raw_value="null"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Similar to the previous comment, removing 2>/dev/null here will improve debuggability by allowing jq errors (e.g., from malformed JSON) to be visible, while the || raw_value="null" construct gracefully handles the failure.

Suggested change
raw_value=$(echo "$json" | jq --arg p "$dotpath" 'getpath($p | split("."))' 2>/dev/null) || raw_value="null"
raw_value=$(echo "$json" | jq --arg p "$dotpath" 'getpath($p | split("."))') || raw_value="null"
References
  1. In shell scripts with 'set -e' enabled, use '|| true' to prevent the script from exiting when a command like 'jq' fails on an optional lookup. Do not suppress stderr with '2>/dev/null' so that actual syntax or system errors remain visible for debugging.

user_val=$(echo "$user_json" | jq -r --arg p "$dotpath" 'getpath($p | split(".")) // empty' 2>/dev/null) || user_val=""
# Get raw JSON value to distinguish null (absent) from false/0
local raw_user_val
raw_user_val=$(echo "$user_json" | jq --arg p "$dotpath" 'getpath($p | split("."))' 2>/dev/null) || raw_user_val="null"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

To align with repository guidelines and improve debugging, please remove the 2>/dev/null. This will allow errors from jq to be reported if $user_json is malformed, which can be very helpful, while still falling back to the null value as intended.

Suggested change
raw_user_val=$(echo "$user_json" | jq --arg p "$dotpath" 'getpath($p | split("."))' 2>/dev/null) || raw_user_val="null"
raw_user_val=$(echo "$user_json" | jq --arg p "$dotpath" 'getpath($p | split("."))') || raw_user_val="null"
References
  1. In shell scripts with 'set -e' enabled, use '|| true' to prevent the script from exiting when a command like 'jq' fails on an optional lookup. Do not suppress stderr with '2>/dev/null' so that actual syntax or system errors remain visible for debugging.

local default_val
default_val=$(echo "$defaults_json" | jq -r --arg p "$dotpath" 'getpath($p | split(".")) // empty' 2>/dev/null) || default_val=""
local raw_default_val default_val
raw_default_val=$(echo "$defaults_json" | jq --arg p "$dotpath" 'getpath($p | split("."))' 2>/dev/null) || raw_default_val="null"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Please remove the 2>/dev/null here as well. Allowing jq to report syntax errors from the defaults file on stderr will make it easier to diagnose issues with the default configuration, without affecting the script's logic thanks to the || fallback.

Suggested change
raw_default_val=$(echo "$defaults_json" | jq --arg p "$dotpath" 'getpath($p | split("."))' 2>/dev/null) || raw_default_val="null"
raw_default_val=$(echo "$defaults_json" | jq --arg p "$dotpath" 'getpath($p | split("."))') || raw_default_val="null"
References
  1. In shell scripts with 'set -e' enabled, use '|| true' to prevent the script from exiting when a command like 'jq' fails on an optional lookup. Do not suppress stderr with '2>/dev/null' so that actual syntax or system errors remain visible for debugging.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Auto-created from TODO.md tag

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug: config-helper.sh _jsonc_get discards false values — boolean configs cannot be set to false

1 participant