zeroclaw-labs/zeroclaw · error
security.otp.gated_actions[{i}] contains invalid characters:
Error message
security.otp.gated_actions[{i}] contains invalid characters: {normalized} What it means
Each entry in security.otp.gated_actions is normalized first (the message prints the normalized form), then must contain only ASCII alphanumerics, '_', or '-'. This character check runs before the membership test against default_otp_gated_actions(), so a malformed name fails here and a well-formed but unknown name fails the subsequent known-actions check. Dotted, coloned, or spaced action names are the usual offenders.
Source
Thrown at crates/zeroclaw-config/src/schema.rs:21420
InvalidNumericRange,
"security.otp.challenge_max_attempts",
"security.otp.challenge_max_attempts must be greater than 0"
);
}
for (i, action) in self.security.otp.gated_actions.iter().enumerate() {
let normalized = action.trim();
if normalized.is_empty() {
validation_bail!(
RequiredFieldEmpty,
format!("security.otp.gated_actions[{i}]"),
"security.otp.gated_actions[{i}] must not be empty"
);
}
if !normalized
.chars()
.all(|c| c.is_ascii_alphanumeric() || c == '_' || c == '-')
{
anyhow::bail!(
"security.otp.gated_actions[{i}] contains invalid characters: {normalized}"
);
}
if !default_otp_gated_actions()
.iter()
.any(|known| known == normalized)
{
::zeroclaw_log::record!(
WARN,
::zeroclaw_log::Event::new(module_path!(), ::zeroclaw_log::Action::Note)
.with_outcome(::zeroclaw_log::EventOutcome::Unknown)
.with_attrs(::serde_json::json!({
"action": normalized,
"known_actions": default_otp_gated_actions(),
})),
"security.otp.gated_actions entry does not match a known gated action and will not be enforced: "
);
}View on GitHub (pinned to 88bb9c8533)
Solutions
- Rewrite the entry using only a-z, A-Z, 0-9, '_', '-': "memory_wipe" instead of "memory.wipe"
- After fixing the charset, confirm the name is one of default_otp_gated_actions() — unknown but well-formed names fail the very next check
- Keep custom action names snake_case or kebab-case to match the existing convention
Example fix
# before [security.otp] gated_actions = ["memory.wipe", "shell_exec"] # after [security.otp] gated_actions = ["memory_wipe", "shell_exec"]
Defensive patterns
Strategy: validation
Validate before calling
fn valid_gated_action(action: &str) -> bool {
action.chars().all(|c| c.is_ascii_alphanumeric() || c == '_' || c == '-')
}
fn gated_actions_precheck(actions: &[String]) -> Result<(), String> {
if let Some(bad) = actions.iter().find(|a| !valid_gated_action(a)) {
return Err(format!("invalid gated action charset: {bad:?}"));
}
Ok(())
} Type guard
fn is_sluglike_action(a: &str) -> bool {
!a.is_empty() && valid_gated_action(a)
} Try / catch
if let Err(err) = config.validate() {
if err.to_string().contains("security.otp.gated_actions") {
// take the index from the message and slugify that entry (dots/colons/spaces -> '_')
}
} Prevention
- Use snake_case or kebab-case when naming gated actions
- Register custom actions in default_otp_gated_actions() before referencing them
- Validate candidate action names with the same charset predicate in your config tooling
When it happens
Trigger: Set gated_actions to an entry like "memory.wipe", "shell exec", "ops:restart", or any string containing '.', ':', ' ', '@', '/' after normalization. The bail fires with the entry's index and normalized value.
Common situations: Inventing new gated actions without registering them in the default set; copying action IDs from a dashboard that renders them as `namespace.action`; merging config from another tool whose action IDs contain dots.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- security.otp.cache_valid_secs must be greater than or equal
- 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
- providers.models.{profile_name}.uri must use http/https
AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23).
Data as JSON: /api/errors/462d9a1ca497c76a.
Report an issue: GitHub.