opf/openproject · error · ActiveRecord::RecordNotFound

AuthProvider with slug: "#{slug}" has not been found

Error message

AuthProvider with slug: "#{slug}" has not been found

What it means

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.

Source

Thrown at app/services/user_auth_provider_links_setter.rb:49

module UserAuthProviderLinksSetter
  private

  def set_user_auth_provider_links(identity_url)
    if identity_url.present?
      slug, external_id = identity_url.split(":", 2)
      if slug.present? && external_id.present?
        auth_provider_id = AuthProvider.where(slug:).pick(:id)
        if auth_provider_id.present?
          link = model.user_auth_provider_links
                   .find_or_initialize_by(auth_provider_id:)
          link.assign_attributes(external_id:, principal: model)
          if link.changed? && link.persisted?
            link.save!
            model.user_auth_provider_links.reload
            model.user_auth_provider_links.find { |l| l.id == link.id }.external_id_will_change!
          end
        else
          raise ActiveRecord::RecordNotFound, "AuthProvider with slug: \"#{slug}\" has not been found"
        end
      end
    end
  end
end

View on GitHub (pinned to d9742c43f3)

Solutions

  1. List the existing slugs and use one of them: AuthProvider.pluck(:slug) (or check Administration → Authentication providers)
  2. Fix the identityUrl payload to reference the correct, existing provider slug
  3. If the provider genuinely should exist, configure it first, then resend the user/group payload
  4. If a provider was renamed, update the external system's stored identityUrl values to the new slug

Example fix

# before — saving a user with an unresolvable provider slug
user_params = { login: 'alice', identityUrl: 'ldap-main:alice' }
# → ActiveRecord::RecordNotFound: AuthProvider with slug: "ldap-main" has not been found

# after — validate the slug before saving
slug = user_params[:identityUrl].to_s.split(":", 2).first
if slug.present? && !AuthProvider.exists?(slug:)
  raise ArgumentError,
        "Unknown AuthProvider slug '#{slug}'. Available: #{AuthProvider.pluck(:slug).join(', ')}"
end
Users::CreateService.new(user: User.new, contract_class: Users::CreateContract)
                     .call(user_params)
Defensive patterns

Strategy: validation

Validate before calling

# before setting identityUrl on a user/group payload
slug = identity_url.to_s.split(":", 2).first
if slug.present? && !AuthProvider.exists?(slug:)
  raise ArgumentError,
        "Unknown AuthProvider slug '#{slug}'. Available: #{AuthProvider.pluck(:slug).join(', ')}"
end

Type guard

# Ruby: shape + resolvability check for identityUrl values
valid_identity_url?(str)
  return false if str.blank?
  slug, external_id = str.split(":", 2)
  slug.present? && external_id.present? && AuthProvider.exists?(slug:)
end

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of opf/openproject@d9742c43f3 (2026-08-21). Data as JSON: /api/errors/8bbcf5d7fa9fb224. Report an issue: GitHub.