libnyanpasu/clash-nyanpasu · error · std::io::Error (Other)

exit code: , signal: , output

Error message

exit code: {:?}, signal: {:?}, output: {}

What it means

The `sudo` helper runs a privileged command via a sudo wrapper (e.g. sudo-prompt/OS auth) and, when the spawned process exits non-zero (or is killed by a signal), reads its captured output file and returns this formatted error containing exit code, signal, and stdout/stderr content.

Solutions

  1. Read the `output:` portion of the error message to see the real command failure.
  2. Retry the operation and make sure the user completes the privilege prompt.
  3. Verify the command string passed to sudo is valid on the platform (e.g. correct networksetup service name).
  4. Handle ErrorKind::Other with a user-facing 'administrator privileges required' message instead of a raw error.

Example fix

// before
sudo(cmd)?;
// after
if let Err(e) = sudo(cmd) {
    log::error!("privileged op failed: {e}");
    return Err(anyhow!("failed to apply system proxy (admin rights required): {e}"));
}
Defensive patterns

Strategy: try-catch

Validate before calling

// cannot pre-validate user auth; verify command args before escalating
assert!(!cmd.contains(";"), "refusing to sudo compound command");

Try / catch

match sudo(cmd) {
    Err(e) if e.kind() == std::io::ErrorKind::Other => report_admin_failure(&e.to_string()),
    other => other?,
}

Prevention

When it happens

Trigger: Calling `sudo` with a command that fails: wrong password/cancelled OS auth prompt, the privileged command itself exits with an error, or the process is terminated by a signal.

Common situations: User cancels the macOS/Windows UAC or polkit authentication dialog; setting system proxy requires admin rights and the user denies them; the underlying command (e.g. networksetup) fails on the target machine.

Related errors


AI-assisted analysis of libnyanpasu/clash-nyanpasu@f7dbce2997 (2026-09-08). Data as JSON: /api/errors/59439131d46075c5. Report an issue: GitHub.

Appendix: source

Thrown at backend/tauri/src/utils/sudo.rs:48

                .as_ref(),
        );
        tracing::debug!("prepare script: {}", script_content);
        std::fs::write(&script, script_content)?;
        let status = std::process::Command::new("osascript")
            .arg("-e")
            .args([&format!(
                r#"do shell script "bash {} &> {}" with administrator privileges"#,
                script.to_string_lossy(),
                out.to_string_lossy()
            )])
            .status();
        match status {
            Ok(status) if status.success() => Ok(()),
            Ok(status) => {
                // read the output file
                let output = std::fs::read_to_string(out)
                    .unwrap_or_else(|e| format!("failed to read output file: {}", e));
                Err(std::io::Error::new(
                    std::io::ErrorKind::Other,
                    format!(
                        "exit code: {:?}, signal: {:?}, output: {}",
                        status.code(),
                        status.signal(),
                        output
                    ),
                ))
            }
            Err(e) => Err(std::io::Error::new(
                std::io::ErrorKind::Other,
                e.to_string(),
            )),
        }
    }
}

#[cfg(target_os = "macos")]

View on GitHub (pinned to f7dbce2997)