zeroclaw-labs/zeroclaw · error

invalid token_validation mode '{other}': expected 'local' or

Error message

invalid token_validation mode '{other}': expected 'local' or 'remote'

What it means

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.

Source

Thrown at crates/zeroclaw-runtime/src/security/nevis.rs:36

    /// When this session expires (seconds since UNIX epoch).
    pub session_expiry: u64,
}

/// Token validation strategy.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum TokenValidationMode {
    /// Validate JWT locally using cached JWKS keys.
    Local,
    /// Validate token by calling the Nevis introspection endpoint.
    Remote,
}

impl TokenValidationMode {
    pub fn from_str_config(s: &str) -> Result<Self> {
        match s.to_ascii_lowercase().as_str() {
            "local" => Ok(Self::Local),
            "remote" => Ok(Self::Remote),
            other => bail!("invalid token_validation mode '{other}': expected 'local' or 'remote'"),
        }
    }
}

/// Authentication model_provider backed by a Nevis instance.
/// Validates tokens, manages sessions, and resolves identities. The model_provider
/// is designed to be shared across concurrent requests (`Send + Sync`).
pub struct NevisAuthProvider {
    /// Base URL of the Nevis instance (e.g. `https://nevis.example.com`).
    instance_url: String,
    /// Nevis realm to authenticate against.
    realm: String,
    /// OAuth2 client ID registered in Nevis.
    client_id: String,
    /// OAuth2 client secret (decrypted at startup).
    client_secret: Option<String>,
    /// Token validation strategy.
    validation_mode: TokenValidationMode,

View on GitHub (pinned to 88bb9c8533)

Solutions

  1. Set the value to exactly 'local' or 'remote' (any case, no surrounding whitespace).
  2. If remote introspection is wanted, use 'remote'; for local JWKS validation use 'local' and also set jwks_url.
  3. Validate the value at config load with a lint/schema check before the provider is constructed.
  4. Watch for whitespace: trim env-sourced values before passing them in.

Example fix

# before
token_validation = "introspection"

# after
token_validation = "remote"   # or "local" with a jwks_url set
Defensive patterns

Strategy: validation

Validate before calling

let mode = token_validation.trim().to_ascii_lowercase();
if !matches!(mode.as_str(), "local" | "remote") {
    anyhow::bail!("token_validation must be 'local' or 'remote', got '{token_validation}'");
}

Type guard

fn is_valid_token_validation_mode(s: &str) -> bool {
    matches!(s.trim().to_ascii_lowercase().as_str(), "local" | "remote")
}

Try / catch

Err(e) if e.to_string().starts_with("invalid token_validation mode") => {
    // surface to the operator with the allowed values; fail deployment, don't guess a default
}

Prevention

When it happens

Trigger: Setting token_validation = "introspection", "jwt", "JWKS", "remot" (typo), or " local" with a leading space; values passed from env vars or templated config without normalization.

Common situations: 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.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23). Data as JSON: /api/errors/0427b8ea5c85f988. Report an issue: GitHub.