Summary
When the terminal's hyperlink string arena is exhausted, the write path appears to spin / not make forward progress instead of dropping the hyperlink and continuing. Writing a large, OSC 8-dense buffer in one shot floods this warning and then pins the thread:
warning(terminal): error reallocating for more hyperlink space, ignoring hyperlink err=error.StringAllocOutOfMemory
The ignoring hyperlink wording suggests the intent is to degrade gracefully, but in practice the containing write does not return.
Environment
ghostty-web@^0.4.0, running as WASM in an Electron renderer (embedded by Nimbalyst).
- Trigger: replaying a terminal's saved scrollback (~500 KB, very hyperlink-dense — Claude Code / Codex emit many OSC 8 clickable file paths) into the terminal in a single write on session restore.
Observed behavior
- A burst of ~70 identical
StringAllocOutOfMemory hyperlink warnings within ~7 ms, then silence.
- The renderer's main thread then sits at ~100% of one core with 0 syscalls over a 6 s
strace sample — i.e. a pure userspace loop, not I/O or a lock.
- A paused JS stack shows the top frame inside the WASM
invoke trampoline — control went into the terminal write and never came back.
So once the arena is full, processing the remaining OSC 8 sequences in that write seems to loop rather than skip-and-advance.
Question / hypothesis
- Is hyperlink-arena exhaustion expected to be recoverable within a single
terminal.write? It looks like the post-failure "ignoring hyperlink" path may retry the allocation (or fail to advance the parser) when the arena stays full for the next hyperlink in the same write, turning many consecutive OSC 8 sequences into an unbounded loop.
- Could you point me to where
StringAllocOutOfMemory from the hyperlink path is handled? If the fix is "drop the hyperlink, advance, and don't re-attempt until space frees", that would turn this from a hang into graceful degradation.
Caveats
I don't yet have a standalone ghostty-web reproduction — this was diagnosed through the Nimbalyst embedding (traces above). If a minimal repro would help, I can try to build one that writes a synthetic OSC 8-dense buffer larger than the arena in a single call; a pointer to the arena size / relevant source would speed that up.
Filing here since ghostty-web owns the WASM build; if this is upstream Ghostty behavior, happy to move it.
Summary
When the terminal's hyperlink string arena is exhausted, the write path appears to spin / not make forward progress instead of dropping the hyperlink and continuing. Writing a large, OSC 8-dense buffer in one shot floods this warning and then pins the thread:
The
ignoring hyperlinkwording suggests the intent is to degrade gracefully, but in practice the containing write does not return.Environment
ghostty-web@^0.4.0, running as WASM in an Electron renderer (embedded by Nimbalyst).Observed behavior
StringAllocOutOfMemoryhyperlink warnings within ~7 ms, then silence.stracesample — i.e. a pure userspace loop, not I/O or a lock.invoketrampoline — control went into the terminal write and never came back.So once the arena is full, processing the remaining OSC 8 sequences in that write seems to loop rather than skip-and-advance.
Question / hypothesis
terminal.write? It looks like the post-failure "ignoring hyperlink" path may retry the allocation (or fail to advance the parser) when the arena stays full for the next hyperlink in the same write, turning many consecutive OSC 8 sequences into an unbounded loop.StringAllocOutOfMemoryfrom the hyperlink path is handled? If the fix is "drop the hyperlink, advance, and don't re-attempt until space frees", that would turn this from a hang into graceful degradation.Caveats
I don't yet have a standalone
ghostty-webreproduction — this was diagnosed through the Nimbalyst embedding (traces above). If a minimal repro would help, I can try to build one that writes a synthetic OSC 8-dense buffer larger than the arena in a single call; a pointer to the arena size / relevant source would speed that up.Filing here since
ghostty-webowns the WASM build; if this is upstream Ghostty behavior, happy to move it.