janhq/jan · error · ServerError
IO error
Error message
IO error: {0} What it means
ServerError::Io wraps a std::io::Error raised inside the tauri-plugin-mlx server and displays as "IO error: {0}". It is produced via `#[from]` whenever an IO operation (file read/write, process spawn, socket) fails while managing the MLX server. It is a transparent wrapper over the OS-level error.
Solutions
- Inspect the inner io::Error (source/kind) for the precise OS cause (NotFound, PermissionDenied, etc.).
- Fix the referenced path: confirm the file/binary exists and has correct permissions.
- Check disk space and directory writability for logs/temp files.
- If it's a socket error, free the occupied port or choose another one.
Example fix
// before
let server = Server::start(config).unwrap();
// after
let server = Server::start(config).map_err(|e| match &e {
ServerError::Io(io) if io.kind() == std::io::ErrorKind::NotFound => {
anyhow!("server binary or model path missing: {}", io)
}
other => anyhow!("server start failed: {other}"),
})?; Defensive patterns
Strategy: try-catch
Validate before calling
// Rust: preflight path checks before starting the server
fn path_ok(p: &Path) -> bool {
p.exists() && std::fs::metadata(p).map(|m| !m.permissions().readonly()).unwrap_or(false)
} Type guard
fn as_io_error(err: &ServerError) -> Option<&std::io::Error> {
match err { ServerError::Io(e) => Some(e), _ => None }
} Try / catch
match Server::start(cfg) {
Err(ServerError::Io(io)) => match io.kind() {
std::io::ErrorKind::NotFound => bail!("missing file: {io}"),
std::io::ErrorKind::PermissionDenied => bail!("fix permissions: {io}"),
_ => bail!("io failure: {io}"),
},
other => other?,
} Prevention
- Verify all file paths and executable permissions before server startup.
- Check free disk space where the server writes logs/temp files.
- Probe ports for availability before binding.
When it happens
Trigger: Starting/stopping the MLX server when a log or model file can't be opened, the server binary can't be spawned, or a port/socket operation fails with an OS error.
Common situations: Wrong model or working-directory paths; missing execute permissions on the server binary; disk-full or permission-denied conditions; port already bound surfacing as an OS error.
Understand the failure class
Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.
Related errors
AI-assisted analysis of janhq/jan@7205d770c1 (2026-09-17).
Data as JSON: /api/errors/11398c2cd9cccd47.
Report an issue: GitHub.
Appendix: source
Thrown at src-tauri/plugins/tauri-plugin-mlx/src/error.rs:62
"Out of memory. The model requires more RAM than available.".into(),
Some(stderr.into()),
);
}
Self::new(
ErrorCode::MlxProcessError,
"The MLX model process encountered an unexpected error.".into(),
Some(stderr.into()),
)
}
}
#[derive(Debug, thiserror::Error)]
pub enum ServerError {
#[error(transparent)]
Mlx(#[from] MlxError),
#[error("IO error: {0}")]
Io(#[from] std::io::Error),
#[error("Tauri error: {0}")]
Tauri(#[from] tauri::Error),
}
impl serde::Serialize for ServerError {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
let error_to_serialize: MlxError = match self {
ServerError::Mlx(err) => err.clone(),
ServerError::Io(e) => MlxError::new(
ErrorCode::IoError,
"An input/output error occurred.".into(),
Some(e.to_string()),
),View on GitHub (pinned to 7205d770c1)