zeroclaw-labs/zeroclaw · error

Nevis introspection returned HTTP {}

Error message

Nevis introspection returned HTTP {}

What it means

In remote mode the provider POSTs to {instance_url}/auth/realms/{realm}/protocol/openid-connect/token/introspect (nevis.rs:167-194). The endpoint answered with a non-2xx status. Typical causes: 401 wrong client_id/client_secret, 404 wrong realm or instance_url path, 5xx IdP or reverse-proxy outage.

Source

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

        let mut form = vec![("token", token), ("client_id", &self.client_id)];
        // client_secret is optional (public clients don't need it)
        let secret_ref;
        if let Some(ref secret) = self.client_secret {
            secret_ref = secret.as_str();
            form.push(("client_secret", secret_ref));
        }

        let resp = self
            .http_client
            .post(&introspect_url)
            .form(&form)
            .send()
            .await
            .context("Failed to reach Nevis introspection endpoint")?;

        if !resp.status().is_success() {
            bail!(
                "Nevis introspection returned HTTP {}",
                resp.status().as_u16()
            );
        }

        let body: IntrospectionResponse = resp
            .json()
            .await
            .context("Failed to parse Nevis introspection response")?;

        if !body.active {
            bail!("Token is not active (revoked or expired)");
        }

        let user_id = body
            .sub
            .filter(|s| !s.trim().is_empty())
            .context("Token has missing or empty `sub` claim")?;

View on GitHub (pinned to 88bb9c8533)

Solutions

  1. Verify client_id and client_secret match a client registered in the same Nevis realm (HTTP 401 is the tell)
  2. Check instance_url and realm — provider.instance_url() and provider.realm() expose what was configured; 404 usually means one is wrong
  3. Run provider.health_check() to confirm the realm root is reachable at all
  4. For 5xx statuses, retry with backoff and a circuit breaker instead of failing every request
Defensive patterns

Strategy: try-catch

Validate before calling

if let Err(e) = provider.health_check().await {
    tracing::warn!(error = %e, "nevis unreachable at startup; token validation may fail");
}

Try / catch

Parse the trailing HTTP code from the message: 401/403 -> fail fast with a config-error alert (credentials); 404 -> alert on realm/URL mismatch; 5xx -> retry with exponential backoff behind a circuit breaker and emit 503 to callers.

Prevention

When it happens

Trigger: validate_token with TokenValidationMode::Remote when the Nevis client credentials are wrong, the realm name is misspelled, instance_url has a wrong prefix, or the IdP/proxy returns 502/503.

Common situations: Client secret rotated on the IdP but not in ZeroClaw config; staging instance_url pasted into prod config; realm 'master' used instead of the actual realm; firewall or mTLS rules blocking the introspection path.

Related errors


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