Skip to content

[Bug]: html_render via nested MCP invocation orphans the page — success message lies, nothing displays #18116

Closed as not planned

Description

@fl-grtg

Before submitting

Area

apps/server

Steps to reproduce

  1. In any thread, invoke html_render nested inside another tool call (outer recorded toolName differs — e.g. an execute sandbox, or emitting a bare reference like [Bug]: visualize output is shown as raw tool text instead of rendering the visualization #7191's visualize{"path":…}), with thread scope.
  2. Call returns success: {htmlRender: {attachmentId, …}, message: "Shown to the reader above your reply…"}.
  3. Observe: no frame in web/desktop/mobile. The file exists at userdata/attachments/<thread>-<uuid>-html.html.

Expected behavior

The page displays — or the call fails honestly.

Actual behavior

Silent orphan. Invisible in all clients, missing from attachment accounting, survives thread deletion and the stale-attachment sweeper (which skips non-pending- files).

Impact

Major degradation or frequent failure

Version or commit

0.0.46-nightly.20261011.2955

Environment

Windows x64, web client (provider-independent — see note)

Logs or stack traces

{"htmlRender": {"attachmentId": "2be2677d-…-d5eeb9f9-…-html", "title": "Yes - demo charts", "height": 408}, "message": "Shown to the reader above your reply. …"}

Workaround

Call html_render directly in the provider tool loop — that path displays on all providers, including OpenCode CLI (per-thread t3-code-<thread>_* spellings resolve). Only nested/sandboxed invocation orphans.

Note (not provider-specific)

This is about the call path, not the provider brand. Direct-loop calls resolve and display (verified in code for mcp__t3-code__html_render and OpenCode per-thread spellings); a Claude/Codex agent invoking from inside a wrapper would orphan exactly the same way.

Evidence

3 orphan -html.html files on disk for one thread; statev2.sqlite: 116 turn items, 44 mention the string, 0 turn items actually named html_render.

Root cause

Handler requires only thread scope (apps/server/src/mcp/toolkits/html/handlers.ts:41-55); publish stores + returns ref, records nothing (apps/server/src/htmlRender/HtmlRender.ts:416-448, cf. comment at :437-439); all discovery scans turn items only (packages/shared/src/toolOutput.ts:186-193, apps/server/src/attachmentStore.ts:123-137; apps/web/src/session-logic.ts:717-730, apps/mobile/src/lib/threadActivity.ts:1781-1795, apps/server/src/orchestration-v2/ProjectionStore.ts:4736-4742/:6245-6260); scope carries no run/node id so nested vs top-level is indistinguishable (apps/server/src/mcp/McpInvocationContext.ts:53-61).

Fix sizing

No small correct fix — fail-fast needs new invocation attribution across adapters (M); self-recording publish needs an MCP→projection write path + dedup (M-L). Verified by 3 independent code+DB checks; details on request.

Activity

  1. juliusmarminge commented on Oct 11, 2026

    @juliusmarminge
    Member

    Note

    Grok responding on behalf of Julius.

    Thanks for the detailed write-up. This is the same problem tracked in #16745: html_render called from inside a wrapper like OpenCode's execute publishes the page, but clients only look for turn items named html_render, so the page never shows and isn't cleaned up on thread delete. That issue also covers the case where the wrapper's output doesn't carry the reference at all. The fix is in progress in #17031.

    Closing this as a duplicate so the discussion stays in one place. If you hit this through a wrapper that #17031 wouldn't cover, please add that detail on #16745.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    duplicateThis issue or pull request already exists

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions