Skip to content

grist(update-choice-options): refuse widgetOptions/choices shape failures by name (#6588) - #6719

Merged
dezren39 merged 1 commit into
mainfrom
queue/fallback-6588-grist-choices-shape
Nov 7, 2026
Merged

dezren39 merged 1 commit into
mainfrom
queue/fallback-6588-grist-choices-shape

Conversation

@dezren39

@dezren39 dezren39 commented Nov 7, 2026 •

Copy link
Copy Markdown
Member

Fixes #6588.

The bug

pm-stack/grist/update-choice-options.py never checked the shape of the stored widgetOptions it read:

  • a string choices was shredded by list() into one-character choices ("code" → ['c', 'o', 'd', 'e']), PATCHed, and then verified as good because read-back compares against the merged value;
  • a non-object widgetOptions died as a raw ValueError traceback out of dict(), breaking the tool's documented exit-code contract;
  • non-string choices entries passed through unchecked and would be written back as JSON 1 / null / true choices.

The fix

  • New check_widget_options: the stored value must be a JSON object, and choices (when present and not null) must be a list of strings. Anything else raises the named WidgetOptionsError with the offending type/entry named.
  • merge_choices validates before merging — so the refusal happens before any PATCH is built and the stored column is untouched on a shape failure.
  • get_widget_options validates what it parses, including invalid JSON (same named error, with the column named).
  • run() catches WidgetOptionsError like the timeout path: clean message on stderr, exit 1 — the documented contract.
  • Null/absent choices keep their existing "no choices" meaning; all existing merge controls are unchanged.

Tests

pm-stack/grist/test_update_choice_options.py — 15 tests, all green on the laptop (python3 -m unittest test_update_choice_options):

  • New merge-level cases: string choices, dict choices, non-object widgetOptions (string/list/number), non-string entries — plus null-choices semantics.
  • New CLI-level cases (stubbed API): string choices, non-object, and invalid-JSON stored values each exit 1 with a clean stderr message and zero PATCHes sent.
  • Against the pre-fix script the suite fails (1 failure + 8 errors), and its output shows the shredding happening (code -> ['c', 'o', 'd', 'e', 'id']).

Filed from a queue-worker fallback shift (broker backend down, #6619): the issue's comments carry the claim and the release.


Autofix with [code]smith
Open in [code]smith · Need help on this PR? Tag @codesmith-bot with what you need.

…ures by name (#6588)

merge_choices shredded a string choices value into one-character choices via list(), passed non-string entries through unchecked, and a non-object widgetOptions died as a raw ValueError out of dict() -- while the read-back verification compared against the merged value, so a corrupted merge verified as good. check_widget_options now validates the stored shape (JSON object; choices, when present and not null, a list of strings) and raises the named WidgetOptionsError before any PATCH is built; get_widget_options validates what it parses (including invalid JSON), and run() maps the error to a clean stderr message and exit 1, matching the documented exit-code contract. Null/absent choices keep their existing no-choices meaning.

Tests: string/dict choices, non-object widgetOptions, and non-string entries refused at merge level; CLI-level cases pin exit 1 with no PATCH sent for string choices, non-object, and invalid-JSON stored values. Existing controls (append order/other keys, idempotence, empty options, duplicate additions, input not mutated, API timeouts) unchanged and green: 15 tests.
@dezren39
dezren39 requested a review from a team as a code owner November 7, 2026 03:13
@coderabbitai

coderabbitai Bot commented Nov 7, 2026

Copy link
Copy Markdown

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 26 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

Learn how review limits work.

Review configuration:

Run configuration

  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 467c6b3c-f272-41ab-b1cf-464628639e83
Commits

Reviewing files that changed from the base of the PR and between 6837735 and fc49b8d.

Files selected for processing: 2

  • pm-stack/grist/test_update_choice_options.py
  • pm-stack/grist/update-choice-options.py
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Nov 7, 2026 •

Copy link
Copy Markdown
Codex Review Summary: ✅ Completed

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-11-07T03:14:59.821807Z fc49b8d PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@dezren39
dezren39 merged commit ae31c5d into main Nov 7, 2026
3 checks passed
@dezren39
dezren39 deleted the queue/fallback-6588-grist-choices-shape branch November 7, 2026 03:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant