{"record":{"id":"0427b8ea5c85f988","repo":"zeroclaw-labs/zeroclaw","slug":"invalid-token-validation-mode-other-expected","errorCode":null,"errorMessage":"invalid token_validation mode '{other}': expected 'local' or 'remote'","messagePattern":"invalid token_validation mode '(.+?)': expected 'local' or 'remote'","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/zeroclaw-runtime/src/security/nevis.rs","lineNumber":36,"sourceCode":"    /// When this session expires (seconds since UNIX epoch).\n    pub session_expiry: u64,\n}\n\n/// Token validation strategy.\n#[derive(Debug, Clone, Copy, PartialEq, Eq)]\npub enum TokenValidationMode {\n    /// Validate JWT locally using cached JWKS keys.\n    Local,\n    /// Validate token by calling the Nevis introspection endpoint.\n    Remote,\n}\n\nimpl TokenValidationMode {\n    pub fn from_str_config(s: &str) -> Result<Self> {\n        match s.to_ascii_lowercase().as_str() {\n            \"local\" => Ok(Self::Local),\n            \"remote\" => Ok(Self::Remote),\n            other => bail!(\"invalid token_validation mode '{other}': expected 'local' or 'remote'\"),\n        }\n    }\n}\n\n/// Authentication model_provider backed by a Nevis instance.\n/// Validates tokens, manages sessions, and resolves identities. The model_provider\n/// is designed to be shared across concurrent requests (`Send + Sync`).\npub struct NevisAuthProvider {\n    /// Base URL of the Nevis instance (e.g. `https://nevis.example.com`).\n    instance_url: String,\n    /// Nevis realm to authenticate against.\n    realm: String,\n    /// OAuth2 client ID registered in Nevis.\n    client_id: String,\n    /// OAuth2 client secret (decrypted at startup).\n    client_secret: Option<String>,\n    /// Token validation strategy.\n    validation_mode: TokenValidationMode,","sourceCodeStart":18,"sourceCodeEnd":54,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/crates/zeroclaw-runtime/src/security/nevis.rs#L18-L54","documentation":"TokenValidationMode::from_str_config received a string that is neither 'local' nor 'remote' (comparison is case-insensitive but not trim-tolerant). This value decides whether Nevis tokens are validated locally against a JWKS endpoint or remotely via introspection, so an unknown mode fails fast at provider construction.","triggerScenarios":"Setting token_validation = \"introspection\", \"jwt\", \"JWKS\", \"remot\" (typo), or \" local\" with a leading space; values passed from env vars or templated config without normalization.","commonSituations":"Config copied from another auth system with different mode names; YAML values quoted with stray whitespace; version migrations renaming the option; uppercase values work ('Local') but padded ones do not.","solutions":["Set the value to exactly 'local' or 'remote' (any case, no surrounding whitespace).","If remote introspection is wanted, use 'remote'; for local JWKS validation use 'local' and also set jwks_url.","Validate the value at config load with a lint/schema check before the provider is constructed.","Watch for whitespace: trim env-sourced values before passing them in."],"exampleFix":"# before\ntoken_validation = \"introspection\"\n\n# after\ntoken_validation = \"remote\"   # or \"local\" with a jwks_url set","handlingStrategy":"validation","validationCode":"let mode = token_validation.trim().to_ascii_lowercase();\nif !matches!(mode.as_str(), \"local\" | \"remote\") {\n    anyhow::bail!(\"token_validation must be 'local' or 'remote', got '{token_validation}'\");\n}","typeGuard":"fn is_valid_token_validation_mode(s: &str) -> bool {\n    matches!(s.trim().to_ascii_lowercase().as_str(), \"local\" | \"remote\")\n}","tryCatchPattern":"Err(e) if e.to_string().starts_with(\"invalid token_validation mode\") => {\n    // surface to the operator with the allowed values; fail deployment, don't guess a default\n}","preventionTips":["Use a config schema/enum parser so invalid modes fail at load with a clear message.","Trim and lowercase env-sourced values before passing them to the provider.","Keep an allow-list test for accepted mode spellings when config formats change."],"tags":["nevis","auth","config","validation","enum-parse"],"backgroundTag":"invalid-config-value","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}