anomalyco / anomalyco/opencode
tui: slot render returning plain string crashes with "Orphan text error"; @opentui/* unimportable in plugins
Open
@kommander is already working on this.
Since Aug 13, 2026.
2.0
- Dominant language
- TypeScript
- Stars
- 209k
- Forks
- 27.5k
- PR merge metrics
- PR metrics pending
Description
Summary
TUI crashes with Orphan text error: "<string>" must have a <text> as a parent when a TUI plugin slot (sidebar.content) returns a plain string from render(). Plugins are effectively forced to return plain strings because importing @opentui/* inside a TUI plugin fails on next-17403 with OPENTUI_FORCE_WCWIDTH already registered with different configuration (host bug).
Environment
- opencode version: 0.0.0-next-17403 (next channel)
- OS: Linux 5.15.0-1081-oracle #87~20.04.1-Ubuntu SMP Mon Apr 28 12:53:11 UTC 2025 (aarch64 / arm64)
- Terminal: VS Code 1.133.0 (
TERM=xterm-256color, truecolor) - Shell: /bin/bash
- Install/channel: next (via
~/.opencode/bin/opencode2) - Active plugins:
usage-tracker.js(server),usage-tracker-tui.js(local TUI plugin at~/.config/opencode/tui/usage-tracker-tui.js)
Reproduction
- Register a TUI plugin claiming the sidebar slot whose
renderreturns a plain string:
import { Plugin } from "@opencode-ai/plugin/tui";
export default Plugin.define({
id: "plain-string-slot",
setup: (ctx) => {
const claim = ctx.ui.slot({
append: "sidebar.content",
render: () => "Usage\nin 545.3k out 125.8k\nre 129.7k cache 139.8M/0\nhit 100% cost $0.2697\ntotal 140.6M steps 68",
});
return () => claim();
},
});
- Open the TUI, navigate to a session view with the sidebar rendered.
- TUI crashes:
Orphan text error: "Usage\nin 545.3k ..." must have a <text> as a parent: box-318 above text-node-554.
Expected Behavior
Either of:
- A plain string returned from a slot
render()is wrapped in a<text>node by the host (so strings are a valid slot payload), or @opentui/*is importable from TUI plugin code so plugins can return proper element trees.
Neither path should crash the TUI. The crash takes down the whole terminal UI, not just the slot.
Actual Behavior
Full TUI crash with the orphan-text error. Stack trace:
Error: Orphan text error: "Usage
in 545.3k out 125.8k
re 129.7k cache 139.8M/0
hit 100% cost $0.2697
total 140.6M steps 68" must have a <text> as a parent: box-318 above text-node-554
at w$ (../../node_modules/.bun/@opentui+solid@0.5.2+b9027845aeff97b0/node_modules/@opentui/solid/index.bun.js:559:17)
at N (../../node_modules/.bun/@opentui+solid@0.5.2+b9027845aeff97b0/node_modules/@opentui/solid/index.bun.js:442:7)
at P (../../node_modules/.bun/@opentui+solid@0.5.2+b9027845aeff97b0/node_modules/@opentui/solid/index.bun.js:311:13)
...
at children (../tui/src/routes/session/sidebar.tsx:66:7)
...
at children (../tui/src/routes/session/index.tsx:1143:22)
Additional Context
- The offending plugin was written to return a plain string only because importing
@opentui/*in a TUI plugin dies withOPENTUI_FORCE_WCWIDTH already registered with different configuration— so onnext-17403there is no working way to render styled TUI content from a plugin slot. - Crash is deterministic: every render of the slot once the plugin has data. Sidebar is unrecoverable while the plugin is active.
- The session being viewed at crash time had 68 steps; the sidebar showed live usage stats (input/output/reasoning/cache/cost).
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.