clap icon indicating copy to clipboard operation
clap copied to clipboard

[clap_complete] use of expect causes panic since writing to stdout may fail

Open gtema opened this issue 7 months ago • 3 comments

Please complete the following tasks

Rust Version

1.86

Clap Version

4.5.50

Minimal reproducible code

#[derive(Parser, Debug, PartialEq)]
#[command(name = "completion-derive")]
struct Opt {
    // If provided, outputs the completion file for given shell
    #[arg(long = "generate", value_enum)]
    generator: Option<Shell>,
    #[command(subcommand)]
    command: Option<Commands>,
}

#[derive(Subcommand, Debug, PartialEq)]
enum Commands {
    #[command(visible_alias = "hint")]
    ValueHint(ValueHintOpt),
............
}

fn print_completions<G: Generator>(generator: G, cmd: &mut Command) {
    generate(
        generator,
        cmd,
        cmd.get_name().to_string(),
        &mut io::stdout(),
    );
}

fn main() {
    let opt = Opt::parse();

    if let Some(generator) = opt.generator {
        let mut cmd = Opt::command();
        eprintln!("Generating completion file for {generator:?}...");
        print_completions(generator, &mut cmd);
    } else {
        println!("{opt:#?}");
    }
}

Steps to reproduce the bug with the above code

The reproducer is not really useful, it would be too big to put here. Technically completion for the big command (in my case it's 5Mb) when piped to the less (similarly to cargo r -p clap_complete --example completion-derive -- --generate bash | less just with the much bigger command) crashes when less aborts (i.e. quitting before reaching the end).

Actual Behaviour

failed to write completion file: Os { code: 32, kind: BrokenPipe, message: "Broken pipe" }

Expected Behaviour

No panic

Additional Context

https://github.com/clap-rs/clap/blob/master/clap_complete/src/aot/shells/bash.rs#L78 (and for other generators as well) use "expect" causing application to crash when writing to the buffer fails. Instead result should be propagated to the caller so that there is a possibility to handle (or ignore) the error. This is not visible with the existing examples, so I assume I face some sort of OS specific thresholds writing to the stdout.

Debug Output

clap_complete should not use expect when writing generated result into the buffer, but instead return the result

gtema avatar May 08 '25 15:05 gtema

Reporting out the error with the existing functions would be a breaking change. Maybe we could add a new try_generate function. On Generator, it could have an inherent impl that calls Generator::generate to avoid breaking other implementers of the Generator trait.

Note that the eprintln! in the reproduction case can also panic for the same reason :)

epage avatar May 08 '25 15:05 epage

oh right. Yeah, adding try_generate is absolutely fine

gtema avatar May 08 '25 16:05 gtema

With #6009 merged, whats left is making generate optional or remove it.

epage avatar May 27 '25 17:05 epage