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
- Use a model that reliably returns a JSON array of objects as instructed
- 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)
- Retry with a stronger model or lower temperature for more format-compliant output
- 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
- Use models that reliably emit JSON arrays; wrap fenced JSON before parsing
- If you intercept/parse the primer LLM output yourself, normalize the root to a list of dicts before it reaches DRIFT
- Add retry logic for format errors — shape mistakes from LLMs are transient
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
- No community reports available. Please provide a list of rep
- Query and document embeddings are not compatible. Please ens
- No intermediate answers found in primer response. Ensure tha
- No follow-up queries found in primer response. Ensure that t
- DRIFT Search query cannot be empty.
AI-assisted analysis of microsoft/graphrag@f40e9a26ce (2026-08-27).
Data as JSON: /api/errors/b090731afee69850.
Report an issue: GitHub.