sinelaw/fresh · critical
TypeScript plugin thread creation failed
Error message
TypeScript plugin thread creation failed: {} What it means
The plugin manager's `new` constructor spawns a dedicated thread for the TypeScript plugin runtime. If thread creation fails it logs the error via tracing, and — only in debug builds (`#[cfg(debug_assertions)]`) — panics with "TypeScript plugin thread creation failed". In release builds the panic is compiled out and the editor continues with plugins unavailable; in debug builds it aborts editor startup.
Solutions
- Check the underlying error `e` in the log line for the OS reason (e.g. 'Os { code: 11, ... }' = EAGAIN).
- Raise the thread/process limit: ulimit -u, container pids cgroup limit, or systemd TasksMax.
- Free threads by reducing concurrently spawned plugin threads, or restart the environment if the limit was leaked.
- As a workaround for development sessions, launch with --no-plugins to skip spawning the TypeScript plugin thread.
Example fix
// before (debug build, thread limit exhausted)
panic!("TypeScript plugin thread creation failed: {}", e);
// after: raise the limit instead of patching code
# ulimit -u 4096 # or raise container pids.max / systemd TasksMax Defensive patterns
Strategy: fallback
Validate before calling
// Rust: check the process/thread budget before spawning (Linux)
let limits = std::fs::read_to_string("/proc/sys/kernel/threads-max")?;
let used: i32 = std::fs::read_to_string("/proc/self/status")?
.lines().find(|l| l.starts_with("Threads:"))
.and_then(|l| l.split_whitespace().nth(1))
.unwrap_or("0").parse()?;
let max: i32 = limits.trim().parse()?;
let can_spawn = used < max - 16; Try / catch
// the spawn returns Result; handle it without panicking even in debug
if let Err(e) = thread::Builder::new().name("ts-plugins".into()).spawn(...) {
tracing::error!("TypeScript plugin thread creation failed: {}", e);
// continue with plugins disabled
} Prevention
- Raise ulimit -u / container pids.max in dev environments.
- Run release builds in constrained environments; the panic only exists in debug_assertions.
- Use --no-plugins when plugin support is not needed for the session.
When it happens
Trigger: Constructing PluginManager::new with plugins enabled (no --no-plugins flag) when std::thread::Builder::spawn returns Err — practically only when the OS refuses to create a thread (thread/resource limits hit, e.g. RLIMIT_NPROC/ulimit -u exhausted, out-of-memory in debug builds, cgroup thread caps).
Common situations: Development/debug builds running under low ulimit -u, containers with low pids.max cgroup limits, or a heavily loaded system that already exhausted the process/thread budget. Never occurs in release builds from this code path.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- Plugin system not active
- editor.spawnProcess is not implemented (missing…
- editor.spawnHostProcess is not implemented (missing…
- openFileInSplit: split
- previewFileInSplit: split
AI-assisted analysis of sinelaw/fresh@67894ca546 (2026-09-13).
Data as JSON: /api/errors/a38381535bd88823.
Report an issue: GitHub.
Appendix: source
Thrown at crates/fresh-editor/src/services/plugins/manager.rs:86
let services = Arc::new(EditorServiceBridge {
command_registry: command_registry.clone(),
dir_context,
theme_cache,
local_plugin_fs,
window_registry: Arc::clone(&window_registry),
});
match PluginThreadHandle::spawn(services) {
Ok(handle) => {
return Self {
inner: Some(handle),
window_registry: Some(window_registry),
pending_injected_commands: Vec::new(),
}
}
Err(e) => {
tracing::error!("Failed to spawn TypeScript plugin thread: {}", e);
#[cfg(debug_assertions)]
panic!("TypeScript plugin thread creation failed: {}", e);
}
}
} else {
tracing::info!("Plugins disabled via --no-plugins flag");
}
Self {
inner: None,
window_registry: None,
pending_injected_commands: Vec::new(),
}
}
#[cfg(not(feature = "plugins"))]
{
let _ = command_registry; // Suppress unused warning
let _ = dir_context; // Suppress unused warning
let _ = theme_cache; // Suppress unused warning
let _ = authority_filesystem; // Suppress unused warningView on GitHub (pinned to 67894ca546)