{"record":{"id":"fa26202542eeeb15","repo":"zeroclaw-labs/zeroclaw","slug":"tool-channel-room-error-invalid-action","errorCode":"tool-channel-room-error-invalid-action","errorMessage":"tool-channel-room-error-invalid-action","messagePattern":"tool-channel-room-error-invalid-action","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/zeroclaw-tools/src/channel_room.rs","lineNumber":45,"sourceCode":"\n    fn as_str(self) -> &'static str {\n        match self {\n            Self::CreateRoom => Self::CREATE_ROOM,\n            Self::InviteUser => Self::INVITE_USER,\n        }\n    }\n}\n\nimpl FromStr for ChannelRoomAction {\n    type Err = anyhow::Error;\n\n    fn from_str(value: &str) -> Result<Self, Self::Err> {\n        match value.trim() {\n            Self::CREATE_ROOM => Ok(Self::CreateRoom),\n            Self::INVITE_USER => Ok(Self::InviteUser),\n            other => {\n                let action = other.to_string();\n                anyhow::bail!(tool_msg_with_args(\n                    \"tool-channel-room-error-invalid-action\",\n                    &[(\"action\", &action)]\n                ))\n            }\n        }\n    }\n}\n\npub struct ChannelRoomTool {\n    channels: ChannelMapHandle,\n    security: Arc<SecurityPolicy>,\n}\n\nimpl ChannelRoomTool {\n    pub fn new(security: Arc<SecurityPolicy>, channels: ChannelMapHandle) -> Self {\n        Self { channels, security }\n    }\n}","sourceCodeStart":27,"sourceCodeEnd":63,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/crates/zeroclaw-tools/src/channel_room.rs#L27-L63","documentation":"ChannelRoomTool's execute parses the required 'action' string through ChannelRoomAction::from_str, which accepts exactly 'create_room' and 'invite_user' after trimming (channel_room.rs:24-25, 39-51). Any other value produces the localized error key tool-channel-room-error-invalid-action with the offending value interpolated. Unlike channel-not-found or create-failed, this error propagates as an Err from Tool::execute (the '?' at channel_room.rs:141) rather than a failed ToolResult.","triggerScenarios":"Invoking the channel_room tool with {\"action\": \"create\"}, {\"action\": \"CreateRoom\"}, {\"action\": \"invite\"}, or any casing/wording variant other than the exact snake_case tokens. Matching is trim-only, so case changes and synonyms are rejected.","commonSituations":"LLM callers improvising action names instead of following the schema enum (parameters_schema advertises [\"create_room\", \"invite_user\"] at channel_room.rs:83), prompt templates written from older docs, and script authors guessing 'new_room' or 'createRoom'.","solutions":["Use one of the two exact values: 'create_room' (requires 'channel'; options: name, topic, invites, visibility, encryption) or 'invite_user' (requires 'channel', 'room_id', 'user_id').","If driving an LLM, include parameters_schema()/description in the prompt so the model sees the enum.","Check the interpolated 'action' value in the error message to spot the exact typo, then correct casing/underscores."],"exampleFix":"// before\nlet result = channel_room.execute(json!({\n    \"action\": \"create\",\n    \"channel\": \"matrix\"\n})).await;\n\n// after\nlet result = channel_room.execute(json!({\n    \"action\": \"create_room\",\n    \"channel\": \"matrix\",\n    \"name\": \"Ops\"\n})).await;","handlingStrategy":"validation","validationCode":"const CHANNEL_ROOM_ACTIONS: [&str; 2] = [\"create_room\", \"invite_user\"];\n\nfn valid_channel_room_action(action: &str) -> bool {\n    CHANNEL_ROOM_ACTIONS.contains(&action.trim())\n}\n\n// before execute:\n// anyhow::ensure!(valid_channel_room_action(&args[\"action\"]), \"invalid channel_room action\");","typeGuard":"fn parse_channel_room_action(value: &str) -> Option<&'static str> {\n    match value.trim() {\n        \"create_room\" => Some(\"create_room\"),\n        \"invite_user\" => Some(\"invite_user\"),\n        _ => None,\n    }\n}","tryCatchPattern":"let action = required_string(&args, \"action\")?;\nlet Some(action) = parse_channel_room_action(action) else {\n    return Ok(ToolResult {\n        success: false,\n        output: ToolOutput::default(),\n        error: Some(format!(\n            \"Unknown action '{action}'. Valid: create_room, invite_user\"\n        )),\n    });\n};","preventionTips":["Validate the action string against the schema enum before calling the tool.","Feed ChannelRoomTool::parameters_schema() into LLM prompts so the model sees the enum values.","Note this error surfaces as Err from execute (not a failed ToolResult), so match on Result, not on success flag."],"tags":["enum","validation","channel","llm-tools","rust","zeroclaw"],"backgroundTag":"invalid-enum-value","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}