BoundaryML/baml · error · anyhow::Error
Playground server error: {e}
Error message
Playground server error: {e} What it means
The run function starts the axum HTTP/WebSocket server for the playground; if axum::serve itself returns an error while accepting/serving connections, it is wrapped in this anyhow error. This is a runtime server failure after successful binding, not a configuration problem.
Source
Thrown at baml_language/crates/baml_lsp_server/src/playground_server.rs:812
seam,
broadcast_tx,
env_state,
io_state,
run_store,
playground_dir_override,
lsp_out_tx,
lsp_runtime,
doc_mirror,
workspace_roots.into(),
access_guard,
current_open_target,
)?;
tracing::info!("Playground: http://localhost:{}", local_addr.port());
axum::serve(listener, app)
.await
.map_err(|e| anyhow::anyhow!("Playground server error: {e}"))
}
#[allow(clippy::too_many_arguments)]
fn build_router(
seam: Arc<PlaygroundSeam>,
broadcast_tx: broadcast::Sender<WsOutMessage>,
env_state: Arc<PlaygroundEnvState>,
io_state: Arc<PlaygroundIoState>,
run_store: Arc<InMemoryRunStore>,
playground_dir_override: Option<PathBuf>,
lsp_out_tx: broadcast::Sender<crate::OutboundFrame>,
lsp_runtime: Arc<crate::lsp_runtime::LspRuntime>,
doc_mirror: DocMirror,
workspace_roots: Arc<[PathBuf]>,
access_guard: PlaygroundAccessGuard,
current_open_target: crate::playground_sender::SharedOpenTarget,
) -> anyhow::Result<Router> {
let value_store = Arc::new(Mutex::new(LiveValueCache::with_max_bytes(View on GitHub (pinned to bd85ce9dee)
Solutions
- Check server logs for the underlying axum/io error to identify the socket failure.
- Raise the file-descriptor limit (ulimit -n) if EMFILE occurred.
- Restart the playground/LSP server to recreate the listener.
- Update axum/tokio if the failure traces to a known framework bug.
Defensive patterns
Strategy: try-catch
Try / catch
match run(...).await {
Err(e) if e.to_string().starts_with("Playground server error") => {
tracing::error!("playground crashed: {e:#}; restarting");
restart_server();
}
Err(e) => return Err(e),
Ok(()) => {}
} Prevention
- Raise the file-descriptor ulimit for long-running LSP processes
- Monitor accept-loop failures and restart the server automatically
- Keep axum/tokio versions current
When it happens
Trigger: axum::serve(listener, app).await returning Err — typically the accept loop failing, e.g. the listener socket being closed under the server, EMFILE (too many open files), or an OS-level socket error mid-serve.
Common situations: File-descriptor exhaustion under many WebSocket connections; system suspend/resume breaking the socket; the process hitting ulimit -n; abnormal termination of the network stack in containers.
Understand the failure class
Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.
Related errors
- {err}
- Could not find an available port in range {}..{}
- Could not bind playground port {port}: {e}. Another process
- network error fetching {url}: {source}
- HTTP {status} fetching {url}
AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12).
Data as JSON: /api/errors/29a7cfd8f41fbe6d.
Report an issue: GitHub.