facebook/flow · critical

failed to spawn LSP log flusher

Error message

failed to spawn LSP log flusher

What it means

The LSP server spawns a background thread that periodically flushes Flow event logs; .expect("failed to spawn LSP log flusher") panics if std::thread::Builder::spawn fails. spawn only fails when the OS cannot create a thread — resource limits (RLIMIT_NPROC, cgroup pids.max) or memory exhaustion. Without this thread, event logs would never be flushed, so the server aborts at startup.

Source

Thrown at rust_port/crates/flow_lsp_server/src/flow_lsp.rs:719

pub fn log_flusher_run() {
    std::thread::Builder::new()
        .name("flow_lsp_log_flusher".to_string())
        .spawn(|| {
            loop {
                std::thread::sleep(Duration::from_secs(5));
                let event_logger_result = flow_tokio_runtime::block_on(async {
                    let event_logger_flush = flow_event_logger_lwt::flush();
                    let interaction_flush = crate::lsp_interaction::flush();
                    let (event_logger_result, ()) =
                        tokio::join!(event_logger_flush, interaction_flush);
                    event_logger_result
                });
                if let Err(err) = event_logger_result {
                    eprintln!("Failed to flush Flow event logs: {}", err);
                }
            }
        })
        .expect("failed to spawn LSP log flusher");
}

use flow_lsp::lsp_fmt;

use crate::jsonrpc::get_next_request_id;
use crate::lsp_interaction;

fn sys_utils_realpath(path: &str) -> Option<String> {
    flow_common::files::cached_canonicalize(std::path::Path::new(path))
        .ok()
        .map(|p| p.to_string_lossy().to_string())
}

fn json_truncate(
    json: &serde_json::Value,
    max_string_length: usize,
    max_child_count: usize,
) -> serde_json::Value {

View on GitHub (pinned to 5c86586199)

Solutions

  1. Raise the process/thread limit: ulimit -u higher, or --pids-limit / cgroup pids.max in containers.
  2. Reduce the number of concurrent LSP/server processes running simultaneously.
  3. Increase available memory or the stack allocation environment if spawn fails due to ENOMEM.
  4. Verify with `ulimit -u` and `cat /proc/sys/kernel/threads-max`, then restart the editor/LSP client.

Example fix

// before (systemd user service / container)
TasksMax=128
// after
TasksMax=4096   # or: docker run --pids-limit=4096
Defensive patterns

Strategy: fallback

Validate before calling

fn can_spawn_thread() -> bool {
    std::thread::Builder::new().spawn(|| {}).map(|h| { let _ = h.join(); true }).unwrap_or(false)
}

Try / catch

match std::panic::catch_unwind(start_flow_lsp) {
    Ok(_) => {},
    Err(_) => eprintln!("LSP failed to start: raise ulimit -u / pids.max"),
}

Prevention

When it happens

Trigger: Starting the Flow LSP server (flow_lsp.rs startup path) in a process that has exhausted its thread/process allowance or cannot allocate the thread stack.

Common situations: Editor-launched LSP servers inside containers with strict pids.max; many concurrent LSP sessions in CI hitting RLIMIT_NPROC; low ulimit -u on macOS/Linux dev machines; memory pressure on large monorepo workstations.

Understand the failure class

Background: "unsupported platform" / "not supported on this platform" errors: what they mean and how to fix them — this error's family across 47 libraries.

Related errors


AI-assisted analysis of facebook/flow@5c86586199 (2026-09-08). Data as JSON: /api/errors/dc90f690f8697acc. Report an issue: GitHub.