stalwartlabs/stalwart · error · ScimError

Conflict

Error message

Conflict

What it means

A SCIM Error with HTTP status 409 ("Conflict"), built by `Error::conflict(detail)` which attaches a human-readable detail. It signals that the request conflicts with the current state of the resource — typically a uniqueness constraint such as a userName or email that already exists.

Source

Thrown at crates/scim-proto/src/message/error.rs:175

            scim_type: Some(ScimType::Uniqueness),
            detail: Some(detail.into()),
        }
    }

    pub fn unauthorized() -> Self {
        Error::new(401)
    }

    pub fn forbidden(detail: impl Into<Cow<'static, str>>) -> Self {
        Error::new(403).with_detail(detail)
    }

    pub fn not_found() -> Self {
        Error::new(404)
    }

    pub fn conflict(detail: impl Into<Cow<'static, str>>) -> Self {
        Error::new(409).with_detail(detail)
    }

    pub fn precondition_failed() -> Self {
        Error::new(412)
    }

    pub fn max_operations_exceeded(max_operations: usize) -> Self {
        Error::new(413).with_detail(format!(
            "The number of operations in the bulk request exceeds the maxOperations ({max_operations})."
        ))
    }

    pub fn max_payload_size_exceeded(max_payload_size: usize) -> Self {
        Error::new(413).with_detail(format!(
            "The size of the bulk operation exceeds the maxPayloadSize ({max_payload_size})."
        ))
    }

View on GitHub (pinned to e962003857)

Solutions

  1. Query for the existing resource by the conflicting unique attribute and update (PUT/PATCH) it instead of creating a new one.
  2. Make provisioning idempotent: on 409, treat the resource as existing and reconcile its attributes.
  3. Adjust the incoming value so it no longer violates the uniqueness constraint.

Example fix

// before
client.create_user(new_user).await?;
// after
match client.create_user(new_user).await {
    Err(e) if e.status() == 409 => client.update_existing_user_by_username(new_user).await?,
    other => other?,
}
Defensive patterns

Strategy: try-catch

Validate before calling

// check uniqueness before creating
let existing = client.query_users(format!("userName eq \"{u}\"")).await?;
if !existing.resources.is_empty() { /* update instead of create */ }

Try / catch

match client.create_user(u).await {
    Err(e) if e.status() == 409 => reconcile_existing(u).await?,
    other => other?,
}

Prevention

When it happens

Trigger: Creating (POST) or updating (PUT/PATCH) a resource whose unique attribute (userName, emails.value, externalId) collides with an existing record, causing the caller to construct `Error::conflict("...")` with a descriptive message.

Common situations: User provisioning retries re-create an already-provisioned user; two identity sources provision the same email concurrently; a rename collides with an existing account.

Understand the failure class

Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.

Related errors


AI-assisted analysis of stalwartlabs/stalwart@e962003857 (2026-09-06). Data as JSON: /api/errors/e336e73fe5254dc7. Report an issue: GitHub.