{"record":{"id":"8bbcf5d7fa9fb224","repo":"opf/openproject","slug":"authprovider-with-slug-slug-has-not-been-fou","errorCode":null,"errorMessage":"AuthProvider with slug: \"#{slug}\" has not been found","messagePattern":"AuthProvider with slug: \"#(.+?)\" has not been found","errorType":"exception","errorClass":"ActiveRecord::RecordNotFound","httpStatus":404,"severity":"error","filePath":"app/services/user_auth_provider_links_setter.rb","lineNumber":49,"sourceCode":"module UserAuthProviderLinksSetter\n  private\n\n  def set_user_auth_provider_links(identity_url)\n    if identity_url.present?\n      slug, external_id = identity_url.split(\":\", 2)\n      if slug.present? && external_id.present?\n        auth_provider_id = AuthProvider.where(slug:).pick(:id)\n        if auth_provider_id.present?\n          link = model.user_auth_provider_links\n                   .find_or_initialize_by(auth_provider_id:)\n          link.assign_attributes(external_id:, principal: model)\n          if link.changed? && link.persisted?\n            link.save!\n            model.user_auth_provider_links.reload\n            model.user_auth_provider_links.find { |l| l.id == link.id }.external_id_will_change!\n          end\n        else\n          raise ActiveRecord::RecordNotFound, \"AuthProvider with slug: \\\"#{slug}\\\" has not been found\"\n        end\n      end\n    end\n  end\nend\n","sourceCodeStart":31,"sourceCodeEnd":55,"githubUrl":"https://github.com/opf/openproject/blob/d9742c43f3424c34b63550f8c03f201fe5c3040c/app/services/user_auth_provider_links_setter.rb#L31-L55","documentation":"UserAuthProviderLinksSetter (included in Users::SetAttributesService and Groups::SetAttributesService) parses the identityUrl attribute as 'slug:external_id', looks up an AuthProvider record by that slug, and raises ActiveRecord::RecordNotFound when no provider with the slug exists. It fires while saving a user or group through the API v3 endpoints or the admin UI whenever identityUrl references an SSO provider slug that is not configured in this OpenProject instance.","triggerScenarios":"POST/PATCH /api/v3/users or /api/v3/groups (or the equivalent admin forms) with identityUrl like 'ldap-main:alice' when no AuthProvider row has slug 'ldap-main'; the slug part before the first colon is matched exactly against the configured providers.","commonSituations":"Provisioning users from an external system that hardcodes provider slugs that were never created or were renamed in OpenProject; typos in the slug; copying payloads between environments (staging → production) where the provider sets differ; a provider renamed after links were established and stale identityUrl values being re-sent.","solutions":["List the existing slugs and use one of them: AuthProvider.pluck(:slug) (or check Administration → Authentication providers)","Fix the identityUrl payload to reference the correct, existing provider slug","If the provider genuinely should exist, configure it first, then resend the user/group payload","If a provider was renamed, update the external system's stored identityUrl values to the new slug"],"exampleFix":"# before — saving a user with an unresolvable provider slug\nuser_params = { login: 'alice', identityUrl: 'ldap-main:alice' }\n# → ActiveRecord::RecordNotFound: AuthProvider with slug: \"ldap-main\" has not been found\n\n# after — validate the slug before saving\nslug = user_params[:identityUrl].to_s.split(\":\", 2).first\nif slug.present? && !AuthProvider.exists?(slug:)\n  raise ArgumentError,\n        \"Unknown AuthProvider slug '#{slug}'. Available: #{AuthProvider.pluck(:slug).join(', ')}\"\nend\nUsers::CreateService.new(user: User.new, contract_class: Users::CreateContract)\n                     .call(user_params)","handlingStrategy":"validation","validationCode":"# before setting identityUrl on a user/group payload\nslug = identity_url.to_s.split(\":\", 2).first\nif slug.present? && !AuthProvider.exists?(slug:)\n  raise ArgumentError,\n        \"Unknown AuthProvider slug '#{slug}'. Available: #{AuthProvider.pluck(:slug).join(', ')}\"\nend","typeGuard":"# Ruby: shape + resolvability check for identityUrl values\nvalid_identity_url?(str)\n  return false if str.blank?\n  slug, external_id = str.split(\":\", 2)\n  slug.present? && external_id.present? && AuthProvider.exists?(slug:)\nend","tryCatchPattern":null,"preventionTips":["Treat provider slugs as part of your environment contract: pin them in provisioning config and update them when providers are renamed","Validate identityUrl payloads against AuthProvider.pluck(:slug) before sending them to the API","When cloning environments, diff the configured provider slugs first"],"tags":["sso","authentication","users","api","record-not-found","openproject-api"],"backgroundTag":"record-not-found","analyzedSha":"d9742c43f3424c34b63550f8c03f201fe5c3040c","analyzedAt":"2026-08-21T14:40:06.829Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}