microsoft/graphrag · error · ValueError

Response must be a list of dictionaries.

Error message

Response must be a list of dictionaries.

What it means

DRIFT search expects the primer LLM response, once parsed, to be a list of dictionaries (one per community report with intermediate_answer, follow_up_queries, score). If the parsed response is any other shape, _process_primer_results raises this ValueError because it cannot extract the required fields.

Source

Thrown at packages/graphrag/graphrag/query/structured_search/drift_search/search.py:157

            intermediate_answer = "\n\n".join([
                i["intermediate_answer"] for i in response if "intermediate_answer" in i
            ])

            follow_ups = [fu for i in response for fu in i.get("follow_up_queries", [])]

            if not follow_ups:
                error_msg = "No follow-up queries found in primer response. Ensure that the primer response includes follow-up queries."
                raise RuntimeError(error_msg)

            score = sum(i.get("score", float("-inf")) for i in response) / len(response)
            response_data = {
                "intermediate_answer": intermediate_answer,
                "follow_up_queries": follow_ups,
                "score": score,
            }
            return DriftAction.from_primer_response(query, response_data)
        error_msg = "Response must be a list of dictionaries."
        raise ValueError(error_msg)

    async def _search_step(
        self,
        global_query: str,
        k_followups: int,
        search_engine: LocalSearch,
        actions: list[DriftAction],
    ) -> list[DriftAction]:
        """
        Perform an asynchronous search step by executing each DriftAction asynchronously.

        Args:
            global_query (str): The global query for the search.
            search_engine (LocalSearch): The local search engine instance.
            actions (list[DriftAction]): A list of actions to perform.

        Returns
        -------

View on GitHub (pinned to f40e9a26ce)

Solutions

  1. Use a model that reliably returns a JSON array of objects as instructed
  2. If you modified the primer prompt or JSON parsing, ensure the root of the parsed response is a list of dicts (unwrap it before passing to DRIFT)
  3. Retry with a stronger model or lower temperature for more format-compliant output
  4. Log the raw response to see what shape the model actually returned and adjust parsing accordingly

Example fix

# before (custom parse returning a wrapped object)
response = json.loads(raw)  # {'reports': [{...}, ...]}

# after
response = json.loads(raw)
if isinstance(response, dict):
    response = response.get('reports', [response])
Defensive patterns

Strategy: type-guard

Type guard

def is_primer_response_list(response) -> bool:
    return isinstance(response, list) and all(isinstance(i, dict) for i in response)

Try / catch

try:
    result = await drift_search.aresolve(query)
except ValueError as e:
    if "Response must be a list of dictionaries" in str(e):
        # model returned wrong shape; retry or preprocess the response
        ...
    raise

Prevention

When it happens

Trigger: Calling DriftSearch.search where the model returns a single JSON object, a bare string, or nested/escaped JSON instead of a list of objects, causing the branch that builds response_data to be skipped and fall through to the raise at the end of _process_primer_results.

Common situations: Local or smaller models wrapping output in markdown fences or returning one merged object, custom prompt tweaks that change the output format, or JSON parsing configured to yield a non-list root (e.g. {'reports': [...]} instead of [...]).

Related errors


AI-assisted analysis of microsoft/graphrag@f40e9a26ce (2026-08-27). Data as JSON: /api/errors/b090731afee69850. Report an issue: GitHub.