Bug: parse_search_queries_response accepts whitespace-only required fields
Describe the bug
parse_search_queries_response accepts JSON entries whose required query or researchGoal field contains only whitespace.
For example:
parse_search_queries_response(
'[{"query": " ", "researchGoal": "goal"}]',
num_queries=3,
)returns:
[
{
"query": "",
"researchGoal": "goal",
},
]The reverse case is also accepted:
parse_search_queries_response(
'[{"query": "query", "researchGoal": " "}]',
num_queries=3,
)returns:
[
{
"query": "query",
"researchGoal": "",
},
]The parser checks the truthiness of the original strings before applying .strip(). Whitespace-only strings therefore pass validation and become empty strings in the returned result.
These entries are subsequently treated as valid Deep Research branches.
To Reproduce
- Check out GPT Researcher
mainat commit:
6f998577d547b1e54ec662dac63583aa11e3b84b- Install the project and test dependencies:
python -m pip install -e ".[test]"- Create
tests/test_deep_research_blank_query_fields.py:
import json
import pytest
from gpt_researcher.skills.deep_research import (
parse_search_queries_response,
)
@pytest.mark.parametrize(
"item",
[
{
"query": " ",
"researchGoal": "goal",
},
{
"query": "query",
"researchGoal": " \t ",
},
],
)
def test_rejects_whitespace_only_search_query_fields(item):
result = parse_search_queries_response(
json.dumps([item]),
num_queries=3,
)
assert result == []- Run:
python -m pytest \
tests/test_deep_research_blank_query_fields.py \
-q- Observe that both parameterized cases fail.
Representative results:
query contains only whitespace:
Expected:
[]
Received:
[
{
"query": "",
"researchGoal": "goal",
},
]researchGoal contains only whitespace:
Expected:
[]
Received:
[
{
"query": "query",
"researchGoal": "",
},
]Expected behavior
A structured query entry should be accepted only when both required fields remain non-empty after whitespace normalization.
An entry whose query or researchGoal becomes empty after .strip() should be excluded.
For example:
parse_search_queries_response(
'[{"query": " ", "researchGoal": "goal"}]',
num_queries=3,
)should return:
[]Valid entries should continue to be trimmed, retained in their original order, and limited by num_queries.
Actual behavior
Whitespace-only strings pass the parser's initial truthiness check. The parser then strips them and returns entries containing empty required fields:
[
{
"query": "",
"researchGoal": "goal",
},
]or:
[
{
"query": "query",
"researchGoal": "",
},
]The empty values are not rejected after normalization.
Screenshots
Not applicable. This is a deterministic parser-level reproduction without a browser, model, or provider request.
Desktop (please complete the following information):
- OS: macOS 15.7.3, arm64
- Browser: Not applicable
- GPT Researcher version: 0.14.7
- Revision:
main@6f998577d547b1e54ec662dac63583aa11e3b84b - Python: 3.12.13
- Installation: Source checkout
Smartphone (please complete the following information):
Not applicable.
Additional context
The structured JSON branch currently validates the unnormalized field values:
queries = [
{
"query": item["query"].strip(),
"researchGoal": item["researchGoal"].strip(),
}
for item in candidate_queries
if (
isinstance(item, dict)
and item.get("query")
and item.get("researchGoal")
)
]In Python, a whitespace-only string is truthy:
bool(" ")
# TrueThe entry therefore passes the filter. Its field is converted to an empty string only afterward:
" ".strip()
# ""generate_search_queries returns the parser result directly:
return parse_search_queries_response(
response,
num_queries,
)The Deep Research workflow then treats each returned item as a research branch:
tasks = [
process_query(query)
for query in serp_queries
]Inside that branch, the parsed value is passed into a new researcher:
researcher = GPTResearcher(
query=serp_query["query"],
...
)The same value is also used when processing the branch results:
results = await self.process_research_results(
query=serp_query["query"],
context=context,
)A whitespace-only researchGoal likewise becomes an empty goal used by later recursive-query construction.
A possible fix is to normalize the required string fields before testing whether they are empty:
queries = []
for item in candidate_queries:
if not isinstance(item, dict):
continue
query = item.get("query")
research_goal = item.get("researchGoal")
if not isinstance(query, str):
continue
if not isinstance(research_goal, str):
continue
query = query.strip()
research_goal = research_goal.strip()
if not query or not research_goal:
continue
queries.append(
{
"query": query,
"researchGoal": research_goal,
}
)Regression coverage should include:
- a whitespace-only
query; - a whitespace-only
researchGoal; - tabs and newlines in otherwise empty fields;
- valid fields with surrounding whitespace;
- a mixture of valid and empty entries;
- preservation of valid-entry order;
- enforcement of
num_queries; - the existing legacy line-based fallback.
Targeted issue and pull-request searches found no existing report for this post-normalization empty-field root.
Source: assafelovic/gpt-researcher