janhq/jan · error · ServerError::Io
IO error: {0}
Error message
IO error: {0} What it means
The ServerError::Io variant (#[from] std::io::Error) in the tauri-plugin-llamacpp plugin. Its Display is "IO error: {0}". When serialized for Tauri it is mapped to a LlamacppError with code IO_ERROR and message "An input/output error occurred.", with the io::Error string preserved in details. It covers filesystem, process-spawn, and pipe failures inside server commands.
Source
Thrown at src-tauri/plugins/tauri-plugin-llamacpp/src/error.rs:197
fn basename(path: &str) -> &str {
path.rsplit(['/', '\\']).next().unwrap_or(path)
}
fn push_library(found: &mut Vec<String>, candidate: &str) {
let candidate = candidate.trim_matches(['\'', '"', '(', ')', ',', '.'].as_ref());
if looks_like_library(candidate) && !found.iter().any(|f| f == candidate) {
found.push(candidate.to_string());
}
}
// Error type for server commands
#[derive(Debug, thiserror::Error)]
pub enum ServerError {
#[error(transparent)]
Llamacpp(#[from] LlamacppError),
#[error("IO error: {0}")]
Io(#[from] std::io::Error),
#[error("Tauri error: {0}")]
Tauri(#[from] tauri::Error),
#[error("Invalid argument: {0}")]
InvalidArgument(String),
}
// impl serialization for tauri
impl serde::Serialize for ServerError {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
let error_to_serialize: LlamacppError = match self {
ServerError::Llamacpp(err) => err.clone(),
ServerError::Io(e) => LlamacppError::new(View on GitHub (pinned to fad3f12a14)
Solutions
- Check file/path permissions and existence for any path the command reads or writes.
- Confirm the llama-server binary is installed and executable (else expect BinaryNotFound for the dedicated case).
- Handle a broken pipe gracefully if the client disconnects during streaming.
- Free disk space if writes are failing.
Example fix
// Rust
pub fn read_model_meta(p: String) -> ServerResult<String> {
let s = std::fs::read_to_string(&p)?; // io::Error -> ServerError::Io
Ok(s)
}
// Frontend
catch (e) {
const err = JSON.parse(e.message)
if (err.code === 'IO_ERROR') showFileAdvice(err.details)
} Defensive patterns
Strategy: try-catch
Validate before calling
import { existsSync, accessSync, constants } from 'fs'
function assertReadable(p: string) {
if (!existsSync(p)) throw new Error(`File missing: ${p}`)
accessSync(p, constants.R_OK)
} Try / catch
try {
await invoke('start_server', { ... })
} catch (e) {
const err = JSON.parse((e as any).message ?? '{}')
if (err.code === 'IO_ERROR') showFileOrPermissionsAdvice(err.details)
else throw e
} Prevention
- Verify file existence and read permissions before invoking commands that read them.
- Ensure the llama-server binary is installed and executable.
- Handle broken-pipe conditions when streaming to a disconnecting client.
When it happens
Trigger: A command uses `?` on io::Result — reading a model file, spawning the llama-server process, writing a pidfile, or reading a pipe — and the io::Error converts into ServerError::Io.
Common situations: Model file path unreadable or permission denied; llama-server binary missing (also surfaces as BinaryNotFound elsewhere); pipe broken when the frontend disconnects mid-stream; disk full.
Related errors
- IO error: {0}
- IO error: {0}
- LlamacppError {{ code: {code:?}, message: "{message}" }}
- Tauri error: {0}
- Invalid argument: {0}
AI-assisted analysis of janhq/jan@fad3f12a14 (2026-08-12).
Data as JSON: /api/errors/4ba5def18fb95e72.
Report an issue: GitHub.