sigoden/aichat · error

{err}

Error message

{err}

What it means

run_loader_command executes an external loader command and, if it exits non-zero, bails with the command's stderr (or a generic non-zero-exit message when stderr is empty). This propagates the external tool's failure text as the library error.

Solutions

  1. Run the failing command manually to see its stderr and fix the underlying cause
  2. Install or update the loader binary referenced by the config
  3. Correct the loader command/args in the configuration file
  4. If stderr was empty, add logging to the loader to expose why it exits non-zero
  5. Verify the URL/path input is valid for that loader

Example fix

// before: loader command missing required arg
loader = ["yt-dlp"]
// after
loader = ["yt-dlp", "--dump-json"]
Defensive patterns

Strategy: try-catch

Validate before calling

const { execFileSync } = require('child_process');
function loaderAvailable(cmd) {
  try { execFileSync(cmd, ['--version'], { stdio: 'ignore' }); return true; }
  catch { return false; }
}

Try / catch

try {
  const docs = await loadUrl(url);
} catch (e) {
  // e.message contains loader stderr; run the command manually to debug
  console.error('loader failed:', e.message);
}

Prevention

When it happens

Trigger: Any load operation that shells out to a configured loader (URL loader, protocol-path loader, recursive URL loader, or a custom loader command) when that command exits with a non-zero status.

Common situations: Loader binary not installed or not on PATH; wrong arguments in the loader config; loader failing on a bad URL/auth; sandbox blocking the command.

Understand the failure class

Background: "git command failed": what it means when a tool shells out to git and git exits non-zero — this error's family across 21 libraries.

Related errors


AI-assisted analysis of sigoden/aichat@82976d349a (2026-09-09). Data as JSON: /api/errors/170ca4aa69fc666d. Report an issue: GitHub.

Appendix: source

Thrown at src/utils/command.rs:141

            v
        })
        .collect();
    let cmd_eval = shell_words::join(&cmd_args);
    debug!("run `{cmd_eval}`");
    let (cmd, args) = cmd_args.split_at(1);
    let cmd = &cmd[0];
    if use_stdout {
        let (success, stdout, stderr) =
            run_command_with_output(cmd, args, None).with_context(|| {
                format!("Unable to run `{cmd_eval}`, Perhaps '{cmd}' is not installed?")
            })?;
        if !success {
            let err = if !stderr.is_empty() {
                stderr
            } else {
                format!("The command `{cmd_eval}` exited with non-zero.")
            };
            bail!("{err}")
        }
        Ok(stdout)
    } else {
        let status = run_command(cmd, args, None).with_context(|| {
            format!("Unable to run `{cmd_eval}`, Perhaps '{cmd}' is not installed?")
        })?;
        if status != 0 {
            bail!("The command `{cmd_eval}` exited with non-zero.")
        }
        let contents = std::fs::read_to_string(&outpath)
            .context("Failed to read file generated by the loader")?;
        Ok(contents)
    }
}

pub fn edit_file(editor: &str, path: &Path) -> Result<()> {
    let mut child = Command::new(editor).arg(path).spawn()?;
    child.wait()?;

View on GitHub (pinned to 82976d349a)