Skip to content

fix: harden REST tools and config loading against empty/malformed input - #18

Merged
robotlearning123 merged 3 commits into
mainfrom
fix/robustness-none-guards
Jul 2, 2026
Merged

fix: harden REST tools and config loading against empty/malformed input#18
robotlearning123 merged 3 commits into
mainfrom
fix/robustness-none-guards

Conversation

@robotlearning123

Copy link
Copy Markdown
Owner

Summary

Two crash-hardening fixes from the 2026-07-01 round-2 audit (independent of open PR #17 — the two PRs share no source files except a trivial CHANGELOG [Unreleased] union), plus a CLAUDE.md accuracy fix.

1. Unguarded backend.get()None at 11 REST call sites (P1)

backend.get() deliberately returns None on an empty 2xx body (gateway/Cloudflare glitch), but only conversations.py and images.py guarded it. The other 11 sites (memory, account ×2, models, custom GPTs, apps, codex ×2, instructions-get, and both writes.py paths) dereferenced the result and sent a raw AttributeError/TypeError traceback to the MCP client. Reproduced pre-fix:

AttributeError: 'NoneType' object has no attribute 'get'   # _fetch_memories(None-client)
  • Read tools now degrade to empty results — same contract as the already-guarded sites.
  • custom_instructions_set (read-modify-write) instead refuses on None: the current state is unknown, and blind-posting only the supplied fields would silently clear the other field on the account. A known-empty {} (fresh account) still allows the write — covered by a dedicated regression test.

2. load_config TypeError on top-level scalar keys (P2)

A user forgetting the [server] header (port = 9001 at top level) killed server startup with TypeError: 'bool' object is not iterable (reproduced). Now a clean, actionable ValueError naming the offending key — consistent with load_config's existing fail-loudly FileNotFoundError.

3. CLAUDE.md drift (docs)

Claimed "25 MCP tool modules" (actual: 10 modules registering 19 of the 25 tools; the 6 SSE tools live in server.py) and a hardcoded "129 passed" that drifts every PR.

Test evidence

Oracle — new tests against the UNFIXED code:

9 failed, 2 passed in 0.29s   # tests/test_none_guards.py (2 passing = behavior-preservation controls)

This branch:

$ .venv/bin/python -m pytest tests/ -q
140 passed, 9 skipped in 0.87s
$ ruff check gpt2agent tests
All checks passed!

(main baseline: 129 passed, 9 skipped)

Notes for reviewer

🤖 Generated with Claude Code

robotlearning123 and others added 2 commits July 1, 2026 22:54
…p-level config keys

backend.get() returns None on an empty 2xx body, but 11 REST call sites
dereferenced the result unguarded, sending raw AttributeError/TypeError
tracebacks to the MCP client. Read tools now degrade to empty results
(matching the already-guarded list_conversations / get_file_info sites).
custom_instructions_set refuses to proceed when the current state is
unreadable (None) — blind-posting only the supplied fields would silently
clear the other one — while a known-empty {} still allows the write.

load_config crashed with TypeError: 'bool' object is not iterable on a
top-level scalar key (a [server] header forgotten); it now raises a clean
actionable ValueError, consistent with its fail-loudly FileNotFoundError.

All 9 new guard tests fail on the unfixed code (repro verified live);
full suite: 140 passed, 9 skipped.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…nt claim

CLAUDE.md claimed 25 tool modules (actual: 10 registering 19 of the 25
tools, the 6 SSE tools live in server.py) and a hardcoded '129 passed'
that drifts every PR.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 2, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@robotlearning123, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 58 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 1a12d47f-8ab7-4357-bbcf-56372a390d3a

📥 Commits

Reviewing files that changed from the base of the PR and between fce859d and c75d246.

📒 Files selected for processing (11)
  • CHANGELOG.md
  • CLAUDE.md
  • gpt2agent/server.py
  • gpt2agent/tools/account.py
  • gpt2agent/tools/apps.py
  • gpt2agent/tools/codex.py
  • gpt2agent/tools/gpts.py
  • gpt2agent/tools/instructions.py
  • gpt2agent/tools/memory.py
  • gpt2agent/tools/writes.py
  • tests/test_none_guards.py
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/robustness-none-guards

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.

@robotlearning123
robotlearning123 merged commit be920af into main Jul 2, 2026
10 checks passed
@robotlearning123
robotlearning123 deleted the fix/robustness-none-guards branch July 2, 2026 13:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant