janhq/jan · error · AgentToolsError

AgentToolsError

Error message

AgentToolsError: {message}

What it means

AgentToolsError is the plugin's unified error type, serialized via thiserror as 'AgentToolsError: {message}'. From<String> strips the core's 'ERROR:' tool-protocol prefix before storing the message, so errors crossing the tool protocol boundary are normalized into this struct.

Solutions

  1. Read the message field after the 'AgentToolsError: ' prefix — the underlying cause is preserved there.
  2. If the message indicates permission denial, grant the required tool/session permissions before retrying.
  3. If it indicates a sandbox/jail violation, adjust the workspace/jail configuration to permit the attempted path or command.
  4. Fix the caller-side tool arguments if the message reflects schema validation failure, and retry the tool call.

Example fix

// before (Rust handler)
return Err("ERROR: tool 'fs_write' not permitted".into());
// after — agent side
match result {
  Err(AgentToolsError { message }) if message.contains("not permitted") => {
    request_session_grant("fs_write")?;
    retry_tool_call()
  }
  other => other,
}
Defensive patterns

Strategy: try-catch

Try / catch

match agent_tools_call(args) {
  Err(e) if e.to_string().starts_with("AgentToolsError: ") => {
    let msg = e.to_string().trim_start_matches("AgentToolsError: ").to_string();
    if msg.contains("not permitted") { request_grant_and_retry()?; }
    else { return Err(anyhow!(msg)); }
  }
  other => other,
}

Prevention

When it happens

Trigger: Any agent-tools command handler (via commands.rs) returns Err containing a string — often converted through From<String> after stripping the 'ERROR:' prefix — including gate denials, jail violations, schema/lookup failures, or workspace errors surfaced by handlers.

Common situations: A tool call is rejected by the permission gate (missing session grants), a command violates the sandbox/jail, or a handler returns an error string that the command layer wraps into AgentToolsError and forwards to the client.

Related errors


AI-assisted analysis of janhq/jan@7205d770c1 (2026-09-17). Data as JSON: /api/errors/3df1f606d5ec2cb9. Report an issue: GitHub.

Appendix: source

Thrown at src-tauri/plugins/tauri-plugin-agent-tools/src/commands.rs:48

//! Note some command names match built-in tool names (`skill_list`,
//! `memory_list`). The commands are the *management* surface; the tools are what
//! the model calls. They are separate namespaces.

use std::path::{Path, PathBuf};

use serde::Serialize;

use crate::memory;
use crate::permissions::ToolPermissions;
use crate::preview::{self, PreviewRoots};
use crate::skills::{self, SkillMeta};
use crate::tools::gate::{self, Decision, PromptKind, SessionGrants};
use crate::tools::jail;
use crate::tools::{handlers, lookup, schema, ImageContentPart, ToolContext};
use crate::workspace;

#[derive(Debug, Clone, Serialize, thiserror::Error)]
#[error("AgentToolsError: {message}")]
pub struct AgentToolsError {
    pub message: String,
}

impl From<String> for AgentToolsError {
    /// Strips the core's `ERROR:` tool-protocol prefix; it is meaningful to the
    /// model, but noise in a dialog.
    fn from(message: String) -> Self {
        let message = message
            .strip_prefix("ERROR:")
            .unwrap_or(&message)
            .trim()
            .to_string();
        Self { message }
    }
}

/// Outcome of a built-in tool execution.

View on GitHub (pinned to 7205d770c1)