{"record":{"id":"b3dfa89b5194406f","repo":"stalwartlabs/stalwart","slug":"unauthorized","errorCode":null,"errorMessage":"Unauthorized","messagePattern":"Unauthorized","errorType":"http","errorClass":"ScimError","httpStatus":401,"severity":"error","filePath":"crates/scim-proto/src/message/error.rs","lineNumber":163,"sourceCode":"\n    pub fn expired_cursor(detail: impl Into<Cow<'static, str>>) -> Self {\n        Self::bad_request(ScimType::ExpiredCursor, detail)\n    }\n\n    pub fn invalid_count(detail: impl Into<Cow<'static, str>>) -> Self {\n        Self::bad_request(ScimType::InvalidCount, detail)\n    }\n\n    pub fn uniqueness(detail: impl Into<Cow<'static, str>>) -> Self {\n        Error {\n            status: 409,\n            scim_type: Some(ScimType::Uniqueness),\n            detail: Some(detail.into()),\n        }\n    }\n\n    pub fn unauthorized() -> Self {\n        Error::new(401)\n    }\n\n    pub fn forbidden(detail: impl Into<Cow<'static, str>>) -> Self {\n        Error::new(403).with_detail(detail)\n    }\n\n    pub fn not_found() -> Self {\n        Error::new(404)\n    }\n\n    pub fn conflict(detail: impl Into<Cow<'static, str>>) -> Self {\n        Error::new(409).with_detail(detail)\n    }\n\n    pub fn precondition_failed() -> Self {\n        Error::new(412)\n    }\n","sourceCodeStart":145,"sourceCodeEnd":181,"githubUrl":"https://github.com/stalwartlabs/stalwart/blob/e96200385781a6a9995a8b839ac27d6c75a983ee/crates/scim-proto/src/message/error.rs#L145-L181","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nlet resp = client.get(\"/scim/v2/Users\").send().await?; // no auth header\n// after\nlet resp = client.get(\"/scim/v2/Users\")\n    .bearer_auth(&access_token)\n    .send().await?;","handlingStrategy":"validation","validationCode":"// client-side: fail fast when no token is available\nlet token = access_token.as_deref().filter(|t| !t.is_empty())\n    .ok_or_else(|| anyhow::anyhow!(\"no SCIM access token; authenticate first\"))?;","typeGuard":null,"tryCatchPattern":"let resp = client.get(&url).bearer_auth(&token).send().await?;\nif resp.status() == StatusCode::UNAUTHORIZED {\n    // refresh token once, then retry\n    refresh_token().await?;\n    let resp = retry_request().await?;\n}","preventionTips":["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."],"tags":["scim","http-401","authentication"],"backgroundTag":"authentication-required","analyzedSha":"e96200385781a6a9995a8b839ac27d6c75a983ee","analyzedAt":"2026-09-06T22:07:17.982Z","contentChangedAt":"2026-09-06T22:07:17.982Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}