googleworkspace/cli · error · GwsError

5

5

Error message

Model Armor API returned status {status}: {resp_text}

What it means

Returned by `sanitize_text()` when the Model Armor regional endpoint (`modelarmor.{location}.rep.googleapis.com/.../templates/{template}:sanitizeUserPrompt` or `:sanitizeModelResponse`) answers with a non-2xx HTTP status. The raw status code and response body are embedded verbatim, so the Google error JSON (e.g. `PERMISSION_DENIED`, `NOT_FOUND`, `INVALID_ARGUMENT`) is the actual diagnostic.

Source

Thrown at crates/google-workspace-cli/src/helpers/modelarmor.rs:274

    let client = crate::client::build_client()?;
    let resp = client
        .post(&url)
        .header("Authorization", format!("Bearer {token}"))
        .header("Content-Type", "application/json")
        .body(body)
        .send()
        .await
        .context("Model Armor request failed")?;

    let status = resp.status();
    let resp_text = resp
        .text()
        .await
        .context("Failed to read Model Armor response")?;

    if !status.is_success() {
        return Err(GwsError::Other(anyhow::anyhow!(
            "Model Armor API returned status {status}: {resp_text}"
        )));
    }

    parse_sanitize_response(&resp_text)
}

/// Make a POST request to Model Armor's regional API endpoint.
async fn model_armor_post(url: &str, body: &str) -> Result<(), GwsError> {
    let token = auth::get_token(&[CLOUD_PLATFORM_SCOPE])
        .await
        .context("Failed to get auth token")?;

    let client = crate::client::build_client()?;
    let resp = client
        .post(url)
        .header("Authorization", format!("Bearer {token}"))
        .header("Content-Type", "application/json")

View on GitHub (pinned to a3768d0e82)

Solutions

  1. Read the embedded body: 404 NOT_FOUND means the template path is wrong — verify with `gws modelarmor projects locations templates list` (Discovery command).
  2. 403 PERMISSION_DENIED: enable the Model Armor API in the template's project and grant the caller `modelarmor.user` (or Editor) on it.
  3. Confirm the template string has all four segments: projects/PROJECT/locations/LOCATION/templates/TEMPLATE with a valid region like us-central1.
  4. 401/invalid token: re-run `gws auth login` or refresh ADC (`gcloud auth application-default login`).

Example fix

# before
gws modelarmor +sanitize-prompt --template my-tmpl --text 'hello'
# -> Model Armor API returned status 404 Not Found: ...NOT_FOUND...

# after — full resource name with project + location
gws modelarmor +sanitize-prompt \
  --template projects/my-proj/locations/us-central1/templates/my-tmpl \
  --text 'hello'
Defensive patterns

Strategy: try-catch

Validate before calling

// Validate the template resource name before calling sanitize_text
fn valid_template_name(t: &str) -> bool {
    let parts: Vec<&str> = t.split('/').collect();
    parts.len() == 6
        && parts[0] == "projects" && !parts[1].is_empty()
        && parts[2] == "locations" && !parts[3].is_empty()
        && parts[4] == "templates" && !parts[5].is_empty()
}

Try / catch

match modelarmor::sanitize_text(&template, text).await {
    Ok(res) => { /* inspect res.filter_match / res.sanitization_details */ }
    Err(GwsError::Other(e)) => {
        let msg = e.to_string();
        if msg.contains("status 404") { eprintln!("template not found: {template}"); }
        else if msg.contains("status 403") { eprintln!("enable modelarmor.googleapis.com and grant modelarmor.user"); }
        else { return Err(e.into()); }
        std::process::exit(1);
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: `gws modelarmor +sanitize-prompt --template projects/P/locations/L/templates/T ...` with a template that does not exist (404); the Model Armor API not enabled in project P (403); a typo'd location like `us-central` or `global` (404); a template name missing the `projects/.../templates/...` segments (400); an expired OAuth token (401).

Common situations: Sanitizing before sending via Gmail helpers with `--sanitize`; template created in one project/location but referenced with another; fresh GCP project where `modelarmor.googleapis.com` was never enabled; using a service account/ADC without the Model Armor User role.

Related errors


AI-assisted analysis of googleworkspace/cli@a3768d0e82 (2026-08-16). Data as JSON: /api/errors/fc7a56f8bc2b451a. Report an issue: GitHub.