can1357/oh-my-pi · error · RpcError

Prompt completed without a text assistant message

Error message

Prompt completed without a text assistant message

What it means

require_assistant_text() is a convenience accessor on the prompt result; it raises when the prompt run finished without producing any assistant message containing text (assistant_text is None). The prompt completed, but no textual reply exists to return.

Source

Thrown at python/omp-rpc/src/omp_rpc/client.py:371

@dataclass(slots=True, frozen=True)
class ListenerErrorEvent:
    listener_kind: str
    source_type: str | None
    listener: Callable[..., None]
    error: BaseException


@dataclass(slots=True, frozen=True)
class PromptTurn:
    events: tuple[RpcAgentEvent, ...]
    messages: tuple[AgentMessage, ...]
    assistant_message: AssistantMessage | None
    assistant_text: str | None

    def require_assistant_text(self) -> str:
        if self.assistant_text is None:
            raise RpcError("Prompt completed without a text assistant message")
        return self.assistant_text


TodoSeed = str | TodoItem | Mapping[str, object]
TodoPhaseSeed = TodoPhase | Mapping[str, object]


@dataclass(slots=True)
class _PendingRequest:
    command: str
    response_queue: queue.Queue[JsonObject | BaseException]


@dataclass(slots=True)
class _PendingHostToolCall:
    cancel_event: threading.Event

View on GitHub (pinned to 9690622007)

Solutions

  1. Inspect result.messages and result.assistant_message first and handle the None case instead of assuming text exists.
  2. Use the full result object (messages, assistant_message) rather than require_assistant_text() when tool-only turns are possible.
  3. Check for aborts/errors in the prompt lifecycle before extracting text.
  4. If the model should always reply with text, adjust the prompt/system instructions to require a final text answer.

Example fix

# before
text = result.require_assistant_text()

# after
if result.assistant_text is None:
    text = "(no text reply; last message: " + str(result.messages[-1] if result.messages else None) + ")"
else:
    text = result.assistant_text
Defensive patterns

Strategy: type-guard

Validate before calling

if result.assistant_text is not None:
    text = result.assistant_text
else:
    text = None

Type guard

def has_assistant_text(result) -> bool:
    return result.assistant_text is not None

Try / catch

try:
    text = result.require_assistant_text()
except RpcError as exc:
    if "without a text assistant message" in str(exc):
        text = ""
    else:
        raise

Prevention

When it happens

Trigger: Calling require_assistant_text() after a prompt that ended in a tool-only turn, an aborted/cancelled run, an error turn, or a model response consisting solely of tool calls with no text.

Common situations: Automation that expects every prompt to yield text but the agent stopped after tool execution; aborted sessions due to timeout; model configured to emit only structured/tool output.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/2ae5d21ec7c2c001. Report an issue: GitHub.