zeroclaw-labs/zeroclaw · error
tool-channel-room-error-invalid-action
tool-channel-room-error-invalid-action
Error message
tool-channel-room-error-invalid-action
What it means
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.
Source
Thrown at crates/zeroclaw-tools/src/channel_room.rs:45
fn as_str(self) -> &'static str {
match self {
Self::CreateRoom => Self::CREATE_ROOM,
Self::InviteUser => Self::INVITE_USER,
}
}
}
impl FromStr for ChannelRoomAction {
type Err = anyhow::Error;
fn from_str(value: &str) -> Result<Self, Self::Err> {
match value.trim() {
Self::CREATE_ROOM => Ok(Self::CreateRoom),
Self::INVITE_USER => Ok(Self::InviteUser),
other => {
let action = other.to_string();
anyhow::bail!(tool_msg_with_args(
"tool-channel-room-error-invalid-action",
&[("action", &action)]
))
}
}
}
}
pub struct ChannelRoomTool {
channels: ChannelMapHandle,
security: Arc<SecurityPolicy>,
}
impl ChannelRoomTool {
pub fn new(security: Arc<SecurityPolicy>, channels: ChannelMapHandle) -> Self {
Self { channels, security }
}
}View on GitHub (pinned to 88bb9c8533)
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.
Example fix
// before
let result = channel_room.execute(json!({
"action": "create",
"channel": "matrix"
})).await;
// after
let result = channel_room.execute(json!({
"action": "create_room",
"channel": "matrix",
"name": "Ops"
})).await; Defensive patterns
Strategy: validation
Validate before calling
const CHANNEL_ROOM_ACTIONS: [&str; 2] = ["create_room", "invite_user"];
fn valid_channel_room_action(action: &str) -> bool {
CHANNEL_ROOM_ACTIONS.contains(&action.trim())
}
// before execute:
// anyhow::ensure!(valid_channel_room_action(&args["action"]), "invalid channel_room action"); Type guard
fn parse_channel_room_action(value: &str) -> Option<&'static str> {
match value.trim() {
"create_room" => Some("create_room"),
"invite_user" => Some("invite_user"),
_ => None,
}
} Try / catch
let action = required_string(&args, "action")?;
let Some(action) = parse_channel_room_action(action) else {
return Ok(ToolResult {
success: false,
output: ToolOutput::default(),
error: Some(format!(
"Unknown action '{action}'. Valid: create_room, invite_user"
)),
});
}; Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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'.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- unknown {}: {other}
- cloud_ops.iac_tools must not be empty when cloud_ops is enab
- gateway.path_prefix contains invalid character '{bad}'; only
- risk_profiles.{profile_alias}.shell_env_passthrough[{i}] is
- security.otp.cache_valid_secs must be greater than or equal
AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23).
Data as JSON: /api/errors/fa26202542eeeb15.
Report an issue: GitHub.