Skip to content

subagent: finish:"error" / MALFORMED_FUNCTION_CALL with empty content is reported to the parent as a successful completion #52378

Description

@rebelliard

Description

Summary

OpenCode reports a failed subagent run to the parent as a successful one.

A Task subagent's last assistant message ended with finish:"error", rawFinish:"MALFORMED_FUNCTION_CALL", content:[], and 0 output tokens. OpenCode then set the child session to idle with outcome:"succeeded", and the parent got state="completed" with "Subagent completed without a text response." The parent cannot tell a provider failure from a real empty answer. In a review panel, an orchestrator can read that as a clean review. This happened 3 times in one session.

Expected Behavior

  • The child ends in an error state (for example idle outcome:"failed", or the existing error outcome), with the provider error attached.
  • The parent receives state="error", and the tool result carries the finish reason (MALFORMED_FUNCTION_CALL) and the provider error text.
  • Optional: retry the failed step once automatically. This failure may be transient (see Frequency below).

Actual Behavior

Evidence from ~/.local/share/opencode/opencode.db (sqlite3 -readonly). I removed prompts and file contents. All other fields are as stored, except providerState, which is trimmed.

Child ses_f0ca68c11ffescNxFG4bNp3AjF, last assistant message (seq 33, 2026-09-30 19:25:35):

{
  "agent": "prosecutor-tests",
  "model": { "id": "vmc/adlc-prosecutor-tests", "providerID": "vercel", "variant": "default" },
  "content": [],
  "finish": "error",
  "rawFinish": "MALFORMED_FUNCTION_CALL",
  "providerState": {
    "routing": {
      "originalModelId": "google/gemini-3.8-flash",
      "finalProvider": "google",
      "modelAttempts": [
        {
          "canonicalSlug": "google/gemini-3.8-flash",
          "success": false,
          "providerAttempts": [
            {
              "provider": "google",
              "success": false,
              "error": "stream finished with error: MALFORMED_FUNCTION_CALL"
            }
          ]
        }
      ]
    }
  },
  "tokens": { "input": 3771, "output": 0, "reasoning": 37, "cache": { "read": 20366, "write": 0 } }
}

Next event (seq 36, 19:25:37):

{ "time": { "created": 1790789137877 }, "outcome": "succeeded" }

Parent (root session), synthetic message seq 2311:

<subagent sessionID="ses_f0ca68c11ffescNxFG4bNp3AjF" state="completed" description="P5 panel 2 tests">
Subagent completed without a text response.
</subagent>

The same pattern appears in two other child sessions:

Child session Last assistant seq finish / rawFinish Output tokens Idle outcome Parent message
ses_f0ca68c11ffescNxFG4bNp3AjF 33 (19:25:35) error / MALFORMED_FUNCTION_CALL 0 succeeded (seq 36) seq 2311, state="completed"
ses_f0ca60ab7ffe7Tp09wDsPvc6Yq 40 (19:26:14) error / MALFORMED_FUNCTION_CALL 0 succeeded (seq 43) seq 2355, state="completed"
ses_f0c89759cffe0N4N0oDTX5gp4M 33 (19:57:20) error / MALFORMED_FUNCTION_CALL 0 succeeded (seq 36) seq 2686, state="completed"

session_v2.idle_outcome is succeeded for all three. Each child made 4–5 valid tool calls before the failing step.

Query used:

sqlite3 -readonly ~/.local/share/opencode/opencode.db "select seq, data from session_message where session_id='<child>' and type in ('assistant','idle') order by seq desc limit 2"

Additional Context

  • Frequency: 3 out of 5 invocations of this subagent in one session. The same model worked earlier that day.
  • Impact: the parent retried by hand, then switched to a different model. The cost was small (≈ $0.12), but an empty "completed" result looks like "no findings" to a reviewing orchestrator.
  • Workaround: tell the orchestrator to treat an empty subagent reply as a failed run, retry once, then switch to another model.
  • rawFinish is mapped in packages/opencode/src/session/llm/ai-sdk.ts. The error seems to get lost where finish:"error" becomes the child's idle outcome or the parent's subagent state.
  • Provider: vercel (AI Gateway). Virtual model vmc/adlc-prosecutor-tests → google/gemini-3.8-flash, routed to Google.
  • Install/channel: latest (Homebrew anomalyco/tap/opencode-v2, plus OpenChamber's bundled opencode-cli, driven via opencode serve). Shell: /bin/zsh.

Possibly related. These issues also report a failed stream that reaches the parent as an empty success, but none of them covers v2 with finish:"error" / MALFORMED_FUNCTION_CALL:

Plugins

@adlc/opencode, opencode.browser, openchamber-agent-tool

OpenCode version

Sessions recorded by v2.0.18 (session_v2.version, OpenChamber's bundled opencode-cli). The same machine also has Homebrew opencode-v2 v2.0.20. I have not checked whether 2.0.19 or 2.0.20 changed this code path.

Steps to reproduce

Intermittent. It depends on the model sending a malformed tool call.

  1. Configure a subagent pinned to a Gemini Flash model (here, through the Vercel AI Gateway).
  2. From a parent session, invoke it with the Task tool, with a tool-heavy brief (read or grep over a large diff).
  3. After several valid tool steps, the provider stream sometimes ends with stream finished with error: MALFORMED_FUNCTION_CALL.
  4. Look at the parent: the task result is state="completed" with "Subagent completed without a text response."

Screenshot and/or share link

No response

Operating System

macOS (Darwin 25.6.0 arm64)

Terminal

xterm-256color (sessions driven through OpenChamber via opencode serve)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions