Bug: parse_search_queries_response accepts whitespace-only required fields

Author: yifanxiong272Created Sep 1, 2026Updated Sep 1, 2026

Describe the bug

parse_search_queries_response accepts JSON entries whose required query or researchGoal field contains only whitespace.

For example:

python
parse_search_queries_response(
    '[{"query": "   ", "researchGoal": "goal"}]',
    num_queries=3,
)

returns:

python
[
    {
        "query": "",
        "researchGoal": "goal",
    },
]

The reverse case is also accepted:

python
parse_search_queries_response(
    '[{"query": "query", "researchGoal": "   "}]',
    num_queries=3,
)

returns:

python
[
    {
        "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

  1. Check out GPT Researcher main at commit:
6f998577d547b1e54ec662dac63583aa11e3b84b
  1. Install the project and test dependencies:
bash
python -m pip install -e ".[test]"
  1. Create tests/test_deep_research_blank_query_fields.py:
python
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 == []
  1. Run:
bash
python -m pytest \
  tests/test_deep_research_blank_query_fields.py \
  -q
  1. 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:

python
parse_search_queries_response(
    '[{"query": "   ", "researchGoal": "goal"}]',
    num_queries=3,
)

should return:

python
[]

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:

python
[
    {
        "query": "",
        "researchGoal": "goal",
    },
]

or:

python
[
    {
        "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:

python
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:

python
bool("   ")
# True

The entry therefore passes the filter. Its field is converted to an empty string only afterward:

python
"   ".strip()
# ""

generate_search_queries returns the parser result directly:

python
return parse_search_queries_response(
    response,
    num_queries,
)

The Deep Research workflow then treats each returned item as a research branch:

python
tasks = [
    process_query(query)
    for query in serp_queries
]

Inside that branch, the parsed value is passed into a new researcher:

python
researcher = GPTResearcher(
    query=serp_query["query"],
    ...
)

The same value is also used when processing the branch results:

python
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:

python
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