opf/openproject · error · ActiveRecord::RecordNotFound
AuthProvider with slug: "#
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.
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
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
- 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
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.
Understand the failure class
Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.
Related errors
- Filter must be a JSON object, got #
- Couldn't find WeekDay with day #
- Failed to parse Jira API response
- Invalid API token. Please check your credentials in the…
- Jira API returned a 401 error. Your authentication token…
AI-assisted analysis of opf/openproject@d9742c43f3 (2026-08-21).
Data as JSON: /api/errors/8bbcf5d7fa9fb224.
Report an issue: GitHub.
Appendix: 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)