bee-san/RustScan · error

Failed to parse execution format.

Error message

Failed to parse execution format.

What it means

ScriptFile::run builds the command from a call_format template. If the script ends up with no call_format (neither script-specific nor a default template applied), run returns the anyhow error 'Failed to parse execution format.' — i.e. there is no template string telling it how to execute the script.

Source

Thrown at src/scripts/mod.rs:245

        debug!("run self {:?}", &self);

        let separator = self.ports_separator.unwrap_or_else(|| ",".into());

        let mut ports_str = self
            .open_ports
            .iter()
            .map(ToString::to_string)
            .collect::<Vec<String>>()
            .join(&separator);
        if let Some(port) = self.trigger_port {
            ports_str = port;
        }

        let mut final_call_format = String::new();
        if let Some(call_format) = self.call_format {
            final_call_format = call_format;
        } else {
            return Err(anyhow!("Failed to parse execution format."));
        }
        let default_template: Template = Template::new(&final_call_format);
        let mut to_run = String::new();

        if final_call_format.contains("{{script}}") {
            let exec_parts_script: ExecPartsScript = ExecPartsScript {
                script: self.path.unwrap().to_str().unwrap().to_string(),
                ip: self.ip.to_string(),
                port: ports_str,
                ipversion: match &self.ip {
                    IpAddr::V4(_) => String::from("4"),
                    IpAddr::V6(_) => String::from("6"),
                },
            };
            to_run = default_template.fill_with_struct(&exec_parts_script)?;
        } else {
            let exec_parts: ExecParts = ExecParts {
                ip: self.ip.to_string(),

View on GitHub (pinned to e9dadb4a30)

Solutions

  1. Add 'call_format' to the script's entry in ~/.rustscan_scripts.toml, e.g. call_format = "bash {{script}} {{file}}"
  2. Rely on built-in defaults by naming the script with a recognized extension (.sh, .py, .pl) so a default template is chosen
  3. Check for typos: the key must be exactly call_format
  4. Update rustscan if your config format predates the current call_format scheme

Example fix

// before: ~/.rustscan_scripts.toml
[my_script]
path = "/scripts/scan.sh"
// after
[my_script]
path = "/scripts/scan.sh"
call_format = "bash {{script}} {{file}}"
Defensive patterns

Strategy: validation

Validate before calling

// Validate every script entry in ~/.rustscan_scripts.toml has call_format
fn validate_call_formats(config: &toml::Value) -> Result<(), String> {
    for (name, entry) in config.as_table().ok_or("config not a table")? {
        if entry.get("call_format").and_then(|v| v.as_str()).is_none() {
            return Err(format!("script '{}' is missing call_format", name));
        }
    }
    Ok(())
}

Type guard

fn has_call_format(script: &ScriptFile) -> bool {
    script.call_format.as_deref().map(|s| !s.is_empty()).unwrap_or(false)
}

Try / catch

match script.run() {
    Ok(output) => println!("{output}"),
    Err(e) if e.to_string().contains("Failed to parse execution format") => {
        eprintln!("Add call_format = \"bash {{{{script}}}} {{{{file}}}}\" to the script's TOML entry");
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling run() on a parsed ScriptFile whose resolved call_format is None: the script's .rustscan_scripts.toml descriptor lacks a 'call_format' and no default call format was configured/applied for that script type.

Common situations: Custom scripts placed in the scripts directory whose descriptor file omits call_format; typos in the TOML key (e.g. 'callformat'); using an interpreter script type that has no built-in default template; older config formats after a rustscan upgrade.

Understand the failure class

Related errors


AI-assisted analysis of bee-san/RustScan@e9dadb4a30 (2026-09-02). Data as JSON: /api/errors/64f48ca8dd063b3f. Report an issue: GitHub.