FoundationAgents/OpenManus · error · ValueError

Empty or invalid response from LLM

Error message

Empty or invalid response from LLM

What it means

Raised in LLM.ask_with_tools() non-streaming branch when the API returns a response with no choices array or an empty message.content. This can be legitimate model behavior (the model emitted nothing, possibly because content went to reasoning or was filtered) rather than a transport failure, so it is treated as a hard ValueError after the request succeeded.

Source

Thrown at app/llm.py:426

                "messages": messages,
            }

            if self.model in REASONING_MODELS:
                params["max_completion_tokens"] = self.max_tokens
            else:
                params["max_tokens"] = self.max_tokens
                params["temperature"] = (
                    temperature if temperature is not None else self.temperature
                )

            if not stream:
                # Non-streaming request
                response = await self.client.chat.completions.create(
                    **params, stream=False
                )

                if not response.choices or not response.choices[0].message.content:
                    raise ValueError("Empty or invalid response from LLM")

                # Update token counts
                self.update_token_count(
                    response.usage.prompt_tokens, response.usage.completion_tokens
                )

                return response.choices[0].message.content

            # Streaming request, For streaming, update estimated token count before making the request
            self.update_token_count(input_tokens)

            response = await self.client.chat.completions.create(**params, stream=True)

            collected_messages = []
            completion_text = ""
            async for chunk in response:
                chunk_message = chunk.choices[0].delta.content or ""
                collected_messages.append(chunk_message)

View on GitHub (pinned to 52a13f2a57)

Solutions

  1. Increase max_tokens (or max_completion_tokens for reasoning models) so the model finishes reasoning and emits content
  2. Retry the request — transient empty completions from load-balanced endpoints often succeed on the next call
  3. Inspect the raw response (log response.choices[0]) to see whether content moved to refusal/tool_calls/reasoning fields and adapt extraction

Example fix

# config.toml before
max_tokens = 128

# after
max_tokens = 4096
Defensive patterns

Strategy: retry

Try / catch

for attempt in range(2):
    try:
        text = await llm.ask_with_tools(messages, tools, stream=False)
        break
    except ValueError as e:
        if "Empty or invalid response" in str(e) and attempt == 0:
            continue
        raise

Prevention

When it happens

Trigger: Calling ask_with_tools(..., stream=False) where the provider returns choices: [] or a message whose content is empty/None; models that put output into refusal or reasoning fields; content-filtered responses from hosted endpoints.

Common situations: Using a reasoning model whose visible content is empty when max_tokens is exhausted mid-reasoning; proxy/gateway rewriting responses and dropping content; aggressive content moderation returning empty completions.

Related errors


AI-assisted analysis of FoundationAgents/OpenManus@52a13f2a57 (2026-08-15). Data as JSON: /api/errors/77ba7c0fa091906d. Report an issue: GitHub.