Skip to content

rest: coerce non-string JSON response values to text#1910

Open
cognis-digital wants to merge 1 commit into
NVIDIA:mainfrom
cognis-digital:fix-rest-nonstring-response
Open

rest: coerce non-string JSON response values to text#1910
cognis-digital wants to merge 1 commit into
NVIDIA:mainfrom
cognis-digital:fix-rest-nonstring-response

Conversation

@cognis-digital

Copy link
Copy Markdown

Summary

Fixes #1888. A response_json_field / JSONPath can resolve to a dict, list, number, or bool rather than a string — observed with some Azure OpenAI REST response shapes. The extracted value flowed unmodified into Message(), and a downstream detector then raised AttributeError: 'dict' object has no attribute 'lower' — only after every subtest in the probe had run, so the whole run was wasted.

Fix

  • Add _coerce_response_text(): passes strings/None through, serializes dict/list to JSON, and str()s other scalars — so the value handed to Message() is always text.
  • In the single-match JSONPath branch, keep a non-str/non-list value (e.g. a dict) instead of silently leaving response = [None] (which discarded a real response).

Tests

Adds test_json_rest_dict_value_is_coerced and test_json_rest_jsonpath_dict_value_is_coerced mirroring the existing requests_mock REST tests: a response field that resolves to a dict now yields a string Message (what detectors call .lower() on) instead of crashing.

Minimal and backwards-compatible: string and list responses are unchanged.

A response_json_field / JSONPath can resolve to a dict, list, number, or bool
rather than a string (seen with some Azure OpenAI response shapes). The value
flowed unmodified into Message(), and a downstream detector then raised
'AttributeError: dict object has no attribute lower' after every subtest had run.

Coerce non-string extracted values to text (dict/list -> JSON, scalar -> str) via
_coerce_response_text, and keep single-match dict values instead of silently
dropping them to [None]. Adds regression tests for the dict-valued field and
JSONPath cases.

@jmartin-tech jmartin-tech left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

How does this offering compare with #1892, I see possible tradeoffs to each.

Comment thread garak/generators/rest.py
if value is None or isinstance(value, str):
return value
if isinstance(value, (dict, list)):
return json.dumps(value, ensure_ascii=False)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This could raise an exception that will not be handled well by the run if the content is not valid json.

@jmartin-tech jmartin-tech changed the title rest: coerce non-string JSON response values to text (fixes #1888) rest: coerce non-string JSON response values to text Jul 8, 2026
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.

AttributeError: 'dict' object has no attribute 'lower' on REST endpoint after any probe finish

2 participants