BoundaryML/baml · error

No candidates found in

Error message

No candidates found in {}

What it means

The optimizer TUI displays candidate trials from a prior optimization run's storage. In non-live mode it requires at least one candidate; if the loaded storage contains none, it bails before entering the terminal UI. Live mode intentionally allows zero candidates because optimization has not started yet.

Solutions

  1. Check the storage_path contents and confirm it is the run directory of a completed (or in-progress) optimization with saved candidates.
  2. Use live mode (`run_tui_live` / the live flag) if you want to watch an optimization from the start with zero candidates.
  3. Run the optimizer again to generate candidates, then open the TUI on the resulting run directory.

Example fix

// before (static TUI on empty run dir)
run_tui(storage_path, config)?;
// after (live mode allows starting with no candidates)
run_tui_live(storage_path, config)?;
Defensive patterns

Strategy: validation

Validate before calling

// Rust: ensure candidates exist before launching the static TUI
let candidates = count_candidates(&storage_path)?; // e.g. read candidates.json
if candidates == 0 {
    eprintln!("{} has no candidates; use live mode or run the optimizer first", storage_path.display());
}

Prevention

When it happens

Trigger: Running the TUI (run_tui, non-live path) pointed at a storage/run directory that contains no candidate data: the run directory exists but optimization produced no trials, the storage_path is wrong/empty, or the run was created but never progressed.

Common situations: Inspecting a run directory that was created but whose optimization never got past the first step; pointing --storage at the wrong directory; viewing results of a crashed run that wrote no candidates.

Understand the failure class

Background: EmptyResultError / "no results found": when an API or scraper succeeds but returns zero rows — this error's family across 9 libraries.

Related errors


AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12). Data as JSON: /api/errors/e58c6afe9690a3d7. Report an issue: GitHub.

Appendix: source

Thrown at engine/baml-runtime/src/optimize/tui.rs:1580

/// Internal TUI runner with optional live reload
fn run_tui_internal(storage_path: &Path, live_mode: bool) -> Result<()> {
    let storage = OptimizationStorage::from_existing(storage_path)
        .context("Failed to open optimization storage")?;

    let mut app = App::from_storage(&storage)?;
    app.live_mode = live_mode;
    app.storage_path_for_reload = Some(storage_path.to_path_buf());

    // Load initial status and config
    if let Ok(config) = storage.load_config() {
        app.total_trials = config.trials;
    }
    app.update_status(&storage);

    // In live mode, allow starting with no candidates (optimization hasn't started yet)
    if !live_mode && app.candidates.is_empty() {
        anyhow::bail!("No candidates found in {}", storage_path.display());
    }

    // Setup terminal
    enable_raw_mode()?;
    let mut stdout = io::stdout();
    execute!(stdout, EnterAlternateScreen, EnableMouseCapture)?;
    let backend = CrosstermBackend::new(stdout);
    let mut terminal = Terminal::new(backend)?;

    // Main loop
    let result = run_app(&mut terminal, &mut app);

    // Cleanup
    disable_raw_mode()?;
    execute!(
        terminal.backend_mut(),
        LeaveAlternateScreen,
        DisableMouseCapture

View on GitHub (pinned to bd85ce9dee)