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
- Dump the Web tool's `input_schema` (e.g. `dbg!(&web.input_schema)`) to see its actual shape
- Update the JSON path in the test if `action`/`enum` moved to a different schema location
- 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
- Build tool input schemas from typed definitions so enum paths cannot drift silently
- When changing a tool's parameter schema, grep tests for the schema path
- Keep a snapshot test of each tool's input_schema
- Avoid hand-written JSON paths in assertions — centralize them
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
- configured Web evidence tool
- Absolute path should not warn
- child assignment
- child-local search
- expected authentication error, got
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 = registryView on GitHub (pinned to 73e0f67d83)