docs/test-and-debug/troubleshooting.mdx
docs/test-and-debug/troubleshooting.mdxBrowse 89 files
2,396 tokens
17,777 bytes
Token encoding: o200k_base
Snapshot ac753b4
← Back to SKILL.md
title: Troubleshooting description: Identify common runtime, terminal, plugin, integration, and test failures and open the canonical fix skill: entry: true intents: [troubleshooting, terminal-reset, ffi-errors, native-loading, runtime-plugins, protocols, test-timeouts]
Troubleshooting
Start with the visible symptom. Run the diagnostic in its row, then open the linked guide for the complete behavior.
Terminal and output
| Symptom | Diagnostic and first action | Canonical guide |
|---|---|---|
| Keys do not echo after exit | On POSIX, run stty -a. The flags -echo or -icanon show unrestored terminal input state. Run reset, then inspect every exit path. SIGKILL cannot run signal handlers or renderer.destroy(). | Lifecycle and cleanup |
| Logs overwrite or corrupt the UI | Read renderer.screenMode, renderer.externalOutputMode, and renderer.consoleMode. Also check OTUI_USE_ALTERNATE_SCREEN and OTUI_OVERRIDE_STDOUT. Use the console overlay for console.*, or use split-footer capture for stdout. Stderr remains separate. | Renderer output modes and Console overlay |
| Main-screen or split-footer rows remain damaged | Confirm the resolved screenMode. Call destroy() before the transport closes. A custom transport needs time to flush shutdown bytes. | Screen modes and custom cleanup |
Node.js and native loading
For a native crash, use Native crash debugging to load matching release symbols and collect a useful report.
| Symptom | Diagnostic and first action | Canonical guide |
|---|---|---|
OpenTUI native FFI is not available for this runtime yet | Run node --version. It must print v26.4.0 or later. Start the ESM app with node --experimental-ffi app.mjs. With --permission, also grant --allow-ffi and native-library read access. | Node.js runtime |
ERR_REQUIRE_ASYNC_MODULE | Find require("@opentui/core") or a CommonJS entry. Change the application to ESM and use import. | Node.js runtime |
| A native package or library is missing | Run bun -e 'console.log(process.platform, process.arch, process.env.OPENTUI_LIBC ? process.env.OPENTUI_LIBC : "glibc")'. Replace bun with node for a Node.js host. Check for the matching @opentui/core-* optional package. An install that omits optional dependencies can defer the failure until native work. | Native artifacts |
Linux reports a loader error for libopentui.so | Compare the selected libc with the target system. Set OPENTUI_LIBC=musl before Core imports on musl. On Alpine, install libstdc++ and libgcc. | Select the Linux libc |
OTUI_ASSET_ROOT must be an absolute directory | Print process.env.OTUI_ASSET_ROOT. Replace a relative value with an absolute path before Core imports. | OTUI_ASSET_ROOT |
Missing OpenTUI asset | Compare the missing key with the exact keys from build-time getNodeAssets(). A configured asset root has no package fallback. Extract or copy the complete asset set. | Runtime assets and Node.js SEA |
Runtime-loaded modules
| Symptom | Diagnostic and first action | Canonical guide |
|---|---|---|
| A runtime-plugin entry says it is Bun-only | Check process.versions.bun. Run the host with Bun. Node.js cannot use these entry points. | Runtime module loading |
| The installer says it is already installed without a specifier | Search the entry graph for a side-effect runtime-plugin support import. Remove it, then call the matching /configure installer once with the complete additional map. | Configure before loading |
| A plugin receives a different Core, React, or Solid singleton | Compare one exported object by identity in the host and plugin. Search for stacked Core and framework installers. Keep one host installer and one complete map. | Choose one installer |
| A second installer call does not replace an existing map value | Record the return values. The first compatible call returns true and later compatible calls return false. Existing keys keep their first installed entries. | Repeated installation |
| A Three.js import fails inside a plugin | Inspect the plugin's exact import. The first-party map exposes only @opentui/three. It does not expose three, three/webgpu, or three/tsl. Deploy those dependencies or add explicit trusted host mappings. | Default module maps |
A dependency under node_modules does not use the host runtime | Check its extension and nearest package.json. Rewriting there supports ESM only. A CommonJS helper that imports runtime modules is not rewritten. | Rewriting behavior |
Solid TSX under node_modules fails or uses the wrong JSX runtime | Check whether the package ships uncompiled JSX or TSX. The Solid transform excludes node_modules. Publish precompiled ESM or load source from outside that directory. | Solid transform order |
| A compiled executable cannot find a plugin | Log the resolved plugin URL. Check that the plugin file and every unmapped dependency exist outside the executable. Runtime support does not embed unknown sidecars. | Executable sidecars and deployment forms |
Integrations and protocols
| Symptom | Diagnostic and first action | Canonical guide |
|---|---|---|
Tree-sitter reports Worker initialization timed out or a generic highlight initialization error | Call await client.initialize() directly to retain the original error. Check the worker, WASM, parser, query, and data paths. Under Node.js permissions, allow workers, asset reads, and data-path writes. | Tree-sitter and runtime assets |
| An image uses Unicode blocks instead of Kitty or Sixel | Log renderer.capabilities, renderer.resolution, and image.effectiveProtocol. Auto mode uses blocks in tmux. Sixel also uses blocks until pixel resolution is available. Check protocol environment overrides. | Image rendering protocol |
| Image output breaks inside a multiplexer | Read renderer.capabilities?.multiplexer. Auto mode chooses blocks in tmux. Explicit Kitty or usable Sixel uses tmux passthrough. Remove unsupported forced protocols. | Image rendering protocol and terminal capabilities |
| An SSH clipboard operation affects the server | Read renderer.capabilities?.remote and the host and terminal result statuses. Host clipboard access targets the SSH server. Use terminal-only for the client clipboard. | Remote clipboard sessions |
triggerNotification() returns false | Read renderer.isDestroyed, renderer.capabilities?.notifications, and renderer.capabilities?.multiplexer. The method returns false after destruction or without a detected protocol. Check OPENTUI_NOTIFICATIONS and OPENTUI_NOTIFICATION_PROTOCOL. | Notifications |
| Notifications fail through tmux or Zellij | In tmux, enable the required passthrough policy. In Zellij, confirm OSC 99 forwarding support. Use an override only when detection misses supported forwarding. | Notification multiplexers |
ThreeRenderable init failed appears once and the view stays blank | Read the logged WebGPU error and check bun-webgpu 0.1.7. The renderable records an initialization failure and does not retry. Fix the cause, then create a new renderable. | ThreeRenderable lifecycle |
Test waits
| Symptom | Diagnostic and first action | Canonical guide |
|---|---|---|
Timed out waiting for visual idle after ... frames | Read the attached frameId, nativeFrameCount, cellsUpdated, and scheduler fields. Stop unintended live rendering or release the live request. Increase maxFrames only when the expected work needs more frames. | Waiting for observable output |
Native builds across worktrees
Zig shares its global cache by default. For repeated native builds across many worktrees, you can also share the project cache:
export ZIG_LOCAL_CACHE_DIR="$HOME/.cache/opentui/zig-local-0.16.0"
bun run build:native
Use a persistent local directory. Use a separate directory for each Zig version. bun run clean does not remove an
external cache.
Next
- Environment variables lists diagnostics and overrides.
- Runtime and platform support owns version, target, permission, and asset rules.
- Deploy an OpenTUI application covers release-specific failures.
Referenced from SKILL.md
SKILL.mdView in source ↗
Source excerpt starting at line 91.SKILL.mdView in source ↗91| `testing`, `test-renderer`, `snapshots`, `frames` | `docs/core-concepts/testing.mdx` |92| `troubleshooting`, `terminal-reset`, `ffi-errors`, `native-loading`, `runtime-plugins`, `protocols`, `test-timeouts` | `docs/test-and-debug/troubleshooting.mdx` |93| `plugins`, `plugin`, `slots`, `registry`, `extensions` | `docs/plugins/slots.mdx` |
Source excerpt starting at line 129.129- `docs/core-concepts/testing.mdx`130- `docs/test-and-debug/troubleshooting.mdx`131- `docs/plugins/slots.mdx`