nikivdev/code · error

failed to select recipe

Error message

failed to select recipe

What it means

`run_recipe` wraps any failure from `select_recipe` with this generic top-level message after printing the specific reason to stderr. The library separates the detailed selector diagnostic (empty/ambiguous/no-match) from the exit error so the CLI exits with a clean failure line.

Source

Thrown at src/recipe.rs:125

    }
    for recipe in filtered {
        println!(
            "{:<7} {:<36} {}",
            recipe.scope.as_str(),
            recipe.id,
            recipe.name
        );
    }
    Ok(())
}

fn run_recipe(opts: RecipeRunOpts) -> Result<()> {
    let recipes = load_recipes(opts.scope, opts.global_dir.as_deref())?;
    let recipe = match select_recipe(&recipes, &opts.selector) {
        Ok(recipe) => recipe,
        Err(err) => {
            eprintln!("{err}");
            bail!("failed to select recipe")
        }
    };

    let cwd = resolve_cwd(opts.cwd.as_deref())?;

    println!(
        "Running recipe {} ({}) from {}",
        recipe.id,
        recipe.scope.as_str(),
        recipe.path.display()
    );
    println!("cwd: {}", cwd.display());
    match &recipe.runner {
        RecipeRunner::Shell { shell, command } => {
            let shell_bin = resolve_shell_bin(shell);
            let shell_cmd = command.trim();
            println!("engine: shell");
            println!("shell: {}", shell_bin);

View on GitHub (pinned to a747e741ae)

Solutions

  1. Read the stderr line above the error (e.g. 'no recipe matched' or the ambiguity list) and use the exact recipe id
  2. List available recipes (the tool's list command) and copy an id verbatim
  3. Quote/validate the selector variable in your shell so it isn't empty
  4. Rename duplicate recipe display names or select by unique id instead of name

Example fix

// before
$ f recipe run "$SEL"
failed to select recipe
// after
$ f recipe list        # find ids
$ f recipe run lint-all  # exact id, no empty variable
Defensive patterns

Strategy: validation

Validate before calling

// preflight: reject empty selectors at the call site
fn ensure_selector(sel: &str) -> Result<&str, String> {
    let t = sel.trim();
    if t.is_empty() { Err("selector must be a non-empty recipe id".into()) } else { Ok(t) }
}

Type guard

fn is_valid_selector(sel: &str) -> bool {
    !sel.trim().is_empty()
}

Try / catch

if let Err(e) = run() {
    let msg = e.to_string();
    if msg.contains("failed to select recipe") {
        eprintln!("see stderr above for the selector detail; run the list command for valid ids");
        std::process::exit(2);
    }
    return Err(e);
}

Prevention

When it happens

Trigger: Calling `run_recipe` (via `run`) with a selector that is empty, matches no recipe, or matches multiple recipes — the real cause is printed on stderr by `select_recipe` (or `ambiguous_selector_error`) just before this bail.

Common situations: Typos in the recipe id on the command line; shell expanding an empty variable (`f recipe run "$MY_SELECTOR"` with unset var); two recipes sharing the same display name; referencing a recipe from a scope/directory that isn't loaded.

Related errors


AI-assisted analysis of nikivdev/code@a747e741ae (2026-09-01). Data as JSON: /api/errors/e68ddfefaa6cbfea. Report an issue: GitHub.