Hmbown/CodeWhale · error

Web action enum

Error message

Web action enum

What it means

A panic from `.expect("Web action enum")` in `small_surface_read_only_child_discovers_web_deferred`. The test walks the Web tool's JSON `input_schema` at `properties.action.enum` and asserts it is an array containing exactly `search` and `fetch`. If the schema omits an `action` property, the enum, or stores a non-array value, `as_array()` returns `None` and the expect panics. It encodes the contract that the child-visible Web tool exposes exactly the search/fetch actions.

Solutions

  1. Dump the Web tool's `input_schema` (e.g. `dbg!(&web.input_schema)`) to see its actual shape
  2. Update the JSON path in the test if `action`/`enum` moved to a different schema location
  3. If the schema intentionally changed, adjust the expected `actions` slice to the new allowed values; if accidental, restore the enum in the tool's schema definition

Example fix

// before
web.input_schema["properties"]["action"]["enum"]
    .as_array()
    .expect("Web action enum");
// after (enum moved under anyOf)
web.input_schema["properties"]["action"]["anyOf"][0]["enum"]
    .as_array()
    .expect("Web action enum");
Defensive patterns

Strategy: validation

Validate before calling

let action = web.input_schema.get("properties")
    .and_then(|p| p.get("action"))
    .and_then(|a| a.get("enum"))
    .and_then(|e| e.as_array());
assert!(action.is_some(), "Web schema lacks properties.action.enum: {:?}", web.input_schema);

Type guard

fn schema_action_enum(schema: &serde_json::Value) -> Option<&Vec<serde_json::Value>> {
    schema.get("properties")?
        .get("action")?
        .get("enum")?
        .as_array()
}

Try / catch

let actions = schema_action_enum(&web.input_schema)
    .unwrap_or_else(|| panic!("Web action enum missing; schema: {}", web.input_schema));

Prevention

When it happens

Trigger: The Web tool's input schema changes: `action` renamed, enum moved to another schema location, schema built without the enum array, or `input_schema` is not a JSON object at the queried path (e.g. `Value::Null` via `/` indexing on a missing key).

Common situations: A developer edits the Web tool's parameter definition (adds modes, renames action values, switches schema representation) without updating this assertion; schema generation code regresses and drops the enum.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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

Appendix: source

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

            .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"}),
        )
        .await
        .expect("child-local search");
    assert!(result.result.content.contains("\"tool_name\":\"Web\""));
    let same_batch = registry

View on GitHub (pinned to 73e0f67d83)