Hmbown/CodeWhale · error

configured Web evidence tool

Error message

configured Web evidence tool

What it means

A panic from `.expect("configured Web evidence tool")` in the test `small_surface_read_only_child_discovers_web_deferred`. The test searches the deferred catalog for a Scout-role child and asserts a tool named "Web" exists with `defer_loading == Some(true)`; if the configured small-surface profile no longer registers a Web evidence tool, `find` returns `None` and the expect panics. This is a configuration/contract drift between the test fixture and the tool surface configuration.

Solutions

  1. Inspect `small_surface_registry(FleetRole::Scout)` and the profile's tool list to confirm a `Web` tool is registered for Scout
  2. Print the catalog (`dbg!(&catalog.iter().map(|t| t.name.clone()).collect::<Vec<_>>())`) to see which tools actually exist
  3. Update the test's expected tool name if the Web tool was intentionally renamed, or restore the Web registration in the Scout profile if the removal was accidental

Example fix

// before
.find(|tool| tool.name == "Web")
.expect("configured Web evidence tool");
// after (if renamed)
.find(|tool| tool.name == "WebSearch")
.expect("configured WebSearch evidence tool");
Defensive patterns

Strategy: validation

Validate before calling

let web = catalog.iter().find(|t| t.name == "Web");
if web.is_none() {
    panic!("Web tool missing from Scout catalog; available: {:?}",
        catalog.iter().map(|t| t.name.as_str()).collect::<Vec<_>>());
}

Type guard

fn find_tool<'a>(catalog: &'a [Tool], name: &str) -> Option<&'a Tool> {
    catalog.iter().find(|t| t.name == name)
}

Try / catch

let web = match catalog.iter().find(|t| t.name == "Web") {
    Some(t) => t,
    None => panic!("configured Web evidence tool missing from Scout catalog"),
};

Prevention

When it happens

Trigger: The Scout small-surface profile stops including a tool named `Web` (renamed tool, changed `small_surface_registry`, or filtering in `deferred_catalog_for_model` removes it), so `catalog.iter().find(|t| t.name == "Web")` yields `None`.

Common situations: A developer renames or relocates the Web tool in the tool catalog; profile changes exclude Web from read-only children; tool-name case changes (e.g. `web_search`) without updating this assertion.

Understand the failure class

Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22). Data as JSON: /api/errors/f0fc93a820d03b89. Report an issue: GitHub.

Appendix: source

Thrown at crates/tui/src/tools/subagent/tests.rs:7897

    );
    let strict = surface.request_tools(surface.catalog.clone(), true);
    assert_eq!(
        strict
            .iter()
            .find(|tool| tool.name == "read")
            .and_then(|tool| tool.strict),
        Some(true)
    );
}

#[tokio::test]
async fn small_surface_read_only_child_discovers_web_deferred() {
    let registry = small_surface_registry(FleetRole::Scout);
    let catalog = registry.deferred_catalog_for_model(&FleetRole::Scout);
    let web = catalog
        .iter()
        .find(|tool| tool.name == "Web")
        .expect("configured Web evidence tool");
    assert_eq!(web.defer_loading, Some(true));
    let actions = web.input_schema["properties"]["action"]["enum"]
        .as_array()
        .expect("Web action enum");
    assert_eq!(actions, &[json!("search"), json!("fetch")]);

    let mut surface = SubAgentToolSurface::new(catalog, &[]);
    assert!(!model_tool_names(model_request_tools(&mut surface)).contains("Web"));
    let request_active = surface.active_names.clone();
    let result = registry
        .execute_from_surface(
            "agent_scout",
            "",
            &mut surface,
            &request_active,
            TOOL_SEARCH_NAME,
            json!({"query": "web", "match": "regex"}),
        )

View on GitHub (pinned to 73e0f67d83)