Skip to content

fix(ai): accept a stringified query_workspace arg instead of crashing#1273

Merged
ocervell merged 1 commit into
ai-resiliencyfrom
fix/ai-query-stringified
Jul 4, 2026
Merged

fix(ai): accept a stringified query_workspace arg instead of crashing#1273
ocervell merged 1 commit into
ai-resiliencyfrom
fix/ai-query-stringified

Conversation

@ocervell

@ocervell ocervell commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

Bug (hit during CLI testing)

🟢Query({"_type": "url", "verified": true})
[ERR] ai Action failed with error: AttributeError: 'str' object has no attribute 'items'
  File ".../secator/ai/actions.py", line 731, in _handle_query
    query_filter = _decrypt_dict(query_filter, ctx.encryptor)
  File ".../secator/ai/actions.py", line 1130, in _decrypt_dict
    for k, v in d.items()

The query_workspace tool schema correctly declares query as type: object, but the model returned it as a JSON string ('{"_type":"url","verified":true}') — a well-known tool-calling quirk where providers serialize nested object params as strings. _handle_query assumed a dict and handed it to _decrypt_dict, which does d.items()AttributeError. It's caught by safe_dispatch_action (so non-fatal — the model retried with curl), but it wastes an iteration and any model that stringifies object args can never use query_workspace. (_decrypt_dict only fires when the encryptor is active, i.e. the default sensitive=True.)

Fix

  • _handle_query: if query is a str, json.loads it before decrypt/search. On a non-JSON string or a non-dict, return a clean, LLM-actionable Error ("query must be a JSON object …") instead of crashing. Mirrors the existing add_finding scalar coercion.
  • _decrypt_dict: no-op backstop on non-dict input.

Tests

TestHandleQuery: stringified query is coerced+searched with the encryptor active (the exact original crash condition); non-JSON string and non-dict each return one clean Error. TestDecryptDict: non-dict input returned unchanged. Full AI suite: no new failures vs branch baseline.

Found while testing ai-testing; targets ai-resiliency (#1241).

🤖 Generated with Claude Code

The query_workspace tool schema declares `query` as an object, but some models/
providers serialize it as a JSON string (a known tool-calling quirk). _handle_query
assumed a dict and passed it straight to _decrypt_dict, which did `d.items()` and
raised `AttributeError: 'str' object has no attribute 'items'` — killing the action
(only surfaced as a retry via safe_dispatch_action). Any model that stringifies the
object arg could never use query_workspace.

Coerce a stringified query back to a dict (json.loads) before decrypt/search, and
return a clean, LLM-actionable Error for a genuinely malformed or non-dict query
instead of crashing. Mirrors the existing add_finding scalar coercion. Also harden
_decrypt_dict to no-op on non-dict input as a backstop.

Tests: stringified query is coerced+searched (with encryptor active — the exact
original crash condition), non-JSON string and non-dict return a clean Error, and
_decrypt_dict returns non-dict input unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NNjPggRSVZ2xnLb7ZxWP5H
@coderabbitai

coderabbitai Bot commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 1257f93f-c73f-4d72-ad90-6daf510bceed

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/ai-query-stringified

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.

@ocervell ocervell merged commit a4c3cd8 into ai-resiliency Jul 4, 2026
1 check passed
@ocervell ocervell deleted the fix/ai-query-stringified branch July 4, 2026 18:06
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