stalwartlabs/stalwart · error · ScimError
Not Found
Error message
Not Found
What it means
This is a SCIM protocol Error carrying HTTP status 404 ("Not Found"), built by the `Error::not_found()` constructor in crates/scim-proto. The library throws it to signal that the addressed SCIM resource (a User, Group, or Enterprise extension endpoint) does not exist on the server. It contains no detail message, only the status code and default reason phrase.
Source
Thrown at crates/scim-proto/src/message/error.rs:171
pub fn uniqueness(detail: impl Into<Cow<'static, str>>) -> Self {
Error {
status: 409,
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!(View on GitHub (pinned to e962003857)
Solutions
- List or query the resource collection first (e.g. GET /Users?filter=userName eq "...") to obtain a valid, currently-existing ID.
- Verify the resource was not deleted and that you are targeting the correct tenant/base URL.
- Check the ID format and that it matches exactly what the server returned earlier (no truncation or case change).
Example fix
// before
let user = client.get_user("stale-id").await?;
// after
if let Some(user) = client.find_user_by_username("jdoe@example.com").await? {
// proceed with user.id
} Defensive patterns
Strategy: validation
Validate before calling
// resolve the ID first and only use IDs returned by the server
let found = client.query_users(format!("userName eq \"{username}\"")).await?;
if found.resources.is_empty() { return Err(anyhow!("user does not exist")); }
let id = found.resources[0].id.clone(); Prevention
- Always obtain resource IDs from a prior GET/QUERY on the same server and tenant.
- Treat 404 as 'may have been deleted' and re-sync your local cache.
- Never hard-code or persist resource IDs across environments.
When it happens
Trigger: Calling any scim-proto error path that invokes `Error::not_found()`, i.e. handling GET/PUT/PATCH/DELETE on a resource ID that the server cannot resolve. In a server implementation this is returned when a lookup by ID yields no record.
Common situations: A client dereferences a stale user ID after the account was deleted; an ID is copied from a different tenant/environment; a typo or wrong-case ID is used in the URL path (e.g. /Users/abc123 with a wrong suffix).
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- Unauthorized
- Forbidden
- Conflict
- 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/594f1f37534af190.
Report an issue: GitHub.