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
- Query for the existing resource by the conflicting unique attribute and update (PUT/PATCH) it instead of creating a new one.
- Make provisioning idempotent: on 409, treat the resource as existing and reconcile its attributes.
- 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
- Make provisioning idempotent: on conflict, look up and PATCH the existing record.
- Check /ServiceProviderConfig uniqueness constraints for the attributes you set.
- Serialize concurrent provisioning jobs for the same identity.
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
- Unauthorized
- Forbidden
- Not Found
- Precondition Failed
- The number of operations in the bulk request exceeds the max
AI-assisted analysis of stalwartlabs/stalwart@e962003857 (2026-09-06).
Data as JSON: /api/errors/e336e73fe5254dc7.
Report an issue: GitHub.