xai-org/x-algorithm · error · PermanentAisFailure

AIS rejected {action_name}: {message}

Error message

AIS rejected {action_name}: {message}

What it means

The Abuse Intervention Service (AIS) response contains an outcome/failure marker, meaning AIS definitively rejected the action. classify_ais_failure wraps this in a PermanentAisFailure because rejection outcomes are not retryable — retrying the same action will fail again.

Source

Thrown at abuse-enforcement-service/service-lib/src/service.rs:928

pub struct PermanentAisFailure(pub String);

impl std::fmt::Display for PermanentAisFailure {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "permanent AIS rejection: {}", self.0)
    }
}

impl std::error::Error for PermanentAisFailure {}

const DETERMINISTIC_AIS_EXCEPTION_CLASSES: &[&str] = &[
    "com.twitter.gizmoduck.thriftscala.ValidationFailed",
];

pub fn classify_ais_failure(action_name: &str, message: &str, resp: &Value) -> anyhow::Error {
    if resp.pointer("/success/outcome/failure").is_some()
        || resp.pointer("/outcome/failure").is_some()
    {
        return anyhow::Error::new(PermanentAisFailure(format!(
            "AIS rejected {action_name}: {message}"
        )));
    }
    if let Some(class) = resp
        .pointer("/aisException/underlyingDetails/exceptionClass")
        .and_then(Value::as_str)
        && DETERMINISTIC_AIS_EXCEPTION_CLASSES.contains(&class)
    {
        let detail = resp
            .pointer("/aisException/underlyingDetails/message")
            .and_then(Value::as_str)
            .unwrap_or("");
        return anyhow::Error::new(PermanentAisFailure(format!(
            "AIS {action_name} raised deterministic {class}: {detail}"
        )));
    }
    anyhow::anyhow!("AIS failure on {action_name}: {message}")
}

View on GitHub (pinned to 24c60942c5)

Solutions

  1. Inspect the {message} field to see the AIS rejection reason
  2. Fix the action payload (valid action name, entity ID, params) per AIS docs
  3. Do not retry — this failure is classified permanent; surface it to the caller or alerting
  4. If rejection is unexpected, verify the AIS policy configuration for your service
Defensive patterns

Strategy: try-catch

Try / catch

let err = classify_ais_response(...); if err.downcast_ref::<PermanentAisFailure>().is_some() { /* dead-letter, no retry */ } else { /* retry with backoff */ }

Prevention

When it happens

Trigger: Calling an AIS enforcement action (via classify_ais_response) where the JSON response has /success/outcome/failure or /outcome/failure, e.g. invalid entity, policy forbids the action, or the action was already applied.

Common situations: Passing a malformed action ID or forbidden enforcement action; attempting to enforce on an entity AIS doesn't support; duplicate submission of an already-enforced decision.

Related errors


AI-assisted analysis of xai-org/x-algorithm@24c60942c5 (2026-08-28). Data as JSON: /api/errors/95392071343ee009. Report an issue: GitHub.