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#
| 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. 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 |
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.