stalwartlabs/stalwart · error · ScimError
Unauthorized
Error message
Unauthorized
What it means
SCIM protocol error constructor `Error::unauthorized()` builds a SCIM Error message with HTTP status 401 and no detail or scimType. It represents an authentication failure: the request lacks valid credentials (missing/invalid bearer token, bad basic auth). This is a library constructor, not a runtime fault — the server code chooses to return it.
Source
Thrown at crates/scim-proto/src/message/error.rs:163
pub fn expired_cursor(detail: impl Into<Cow<'static, str>>) -> Self {
Self::bad_request(ScimType::ExpiredCursor, detail)
}
pub fn invalid_count(detail: impl Into<Cow<'static, str>>) -> Self {
Self::bad_request(ScimType::InvalidCount, detail)
}
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)
}
View on GitHub (pinned to e962003857)
Solutions
- Ensure the client sends `Authorization: Bearer <valid-token>` on every SCIM request.
- Refresh expired access tokens before retrying the request.
- Verify the auth middleware/issuer configuration agrees with the token's issuer and audience.
- Check the response body/status (401 with no detail) — if you are the server author, consider `Error::new(401).with_detail(...)` for a more actionable message.
Example fix
// before
let resp = client.get("/scim/v2/Users").send().await?; // no auth header
// after
let resp = client.get("/scim/v2/Users")
.bearer_auth(&access_token)
.send().await?; Defensive patterns
Strategy: validation
Validate before calling
// client-side: fail fast when no token is available
let token = access_token.as_deref().filter(|t| !t.is_empty())
.ok_or_else(|| anyhow::anyhow!("no SCIM access token; authenticate first"))?; Try / catch
let resp = client.get(&url).bearer_auth(&token).send().await?;
if resp.status() == StatusCode::UNAUTHORIZED {
// refresh token once, then retry
refresh_token().await?;
let resp = retry_request().await?;
} Prevention
- Attach the bearer token to every SCIM request via a shared HTTP client middleware.
- Proactively refresh tokens before expiry rather than on 401.
- Verify the token's audience/scope matches the SCIM service's expectations.
When it happens
Trigger: Server code calling `scim_proto::Error::unauthorized()` to respond to a SCIM request whose Authorization header is missing, malformed, or contains an expired/invalid token; `Error::new(401)` is used for every 401 response.
Common situations: Client omitted the Authorization header; expired OAuth2/JWT access token sent to a SCIM endpoint; wrong auth scheme (Basic vs Bearer); token audience/scope not accepted by the SCIM service.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- Forbidden
- Not Found
- 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/b3dfa89b5194406f.
Report an issue: GitHub.