janhq/jan · error · ServerError
Invalid argument
Error message
Invalid argument: {0} What it means
ServerError::InvalidArgument is thrown when a command receives a parameter that fails validation, displayed as "Invalid argument: {0}" with a descriptive message. Unlike the #[from] variants it must be constructed explicitly, so it marks caller-supplied input problems rather than environmental failures. It is the plugin's contract-violation signal for IPC calls.
Solutions
- Read the embedded message; it names the offending parameter and the violated rule.
- Validate inputs on the frontend before invoking the command.
- Fix the calling code to send values matching the command's expected types and ranges.
- Check for recent signature changes between frontend invoke calls and Rust command definitions.
Example fix
// before: sending unvalidated input from the UI
invoke('start_server', { modelPath: userInput });
// after
if (!userInput || !userInput.endsWith('.gguf')) throw new Error('modelPath required');
invoke('start_server', { modelPath: userInput }); Defensive patterns
Strategy: validation
Validate before calling
function validateStartArgs(args) {
if (!args.modelPath || typeof args.modelPath !== 'string' || !args.modelPath.endsWith('.gguf'))
throw new Error('modelPath must be a .gguf file path');
if (args.contextSize != null && (!Number.isInteger(args.contextSize) || args.contextSize <= 0))
throw new Error('contextSize must be a positive integer');
} Type guard
function isValidStartArgs(a) {
return typeof a === 'object' && a !== null
&& typeof a.modelPath === 'string' && a.modelPath.length > 0;
} Try / catch
try {
await invoke('start_server', { modelPath });
} catch (msg) {
if (String(msg).startsWith('Invalid argument:')) {
showInputError(String(msg).slice('Invalid argument:'.length));
} else { throw msg; }
} Prevention
- Validate all inputs in the UI layer before invoke().
- Mirror Rust command signatures exactly in frontend invoke payloads.
- Keep a shared schema for command parameters to catch drift early.
- Never send empty strings or null where the command expects a value.
When it happens
Trigger: A #[tauri::command] validates its inputs (empty model name, malformed path, out-of-range port, negative context size) and returns ServerError::InvalidArgument(String) with the reason.
Common situations: Frontend sends an empty or null-ish model path, a bad temperature/seed value, or a path with unexpected characters; API changes leave the UI sending stale parameter shapes.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
AI-assisted analysis of janhq/jan@7205d770c1 (2026-09-17).
Data as JSON: /api/errors/cae57aed2ae272c0.
Report an issue: GitHub.
Appendix: source
Thrown at src-tauri/plugins/tauri-plugin-llamacpp/src/error.rs:205
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(
ErrorCode::IoError,
"An input/output error occurred.".into(),
Some(e.to_string()),
),
ServerError::Tauri(e) => LlamacppError::new(
ErrorCode::InternalError,View on GitHub (pinned to 7205d770c1)