instructure/canvas-lms · error · GraphQL::ExecutionError
Unauthorized
Error message
Unauthorized
What it means
Raised when the enrollment found by uuid does not belong to the current user (enrollment.user != current_user). The mutation only lets the invited user reject their own invitation, preventing users from rejecting others' enrollments.
Solutions
- Log in as the user the enrollment belongs to before rejecting
- Match the invitation email's target account (check email address vs active session)
- If an admin must reject, use the enrollments admin API instead of this user-scoped mutation
- Verify enrollment.user_id == current_user.id before calling
Example fix
// before
rejectEnrollmentInvitation(forwardedUuid) // session user != invitee
// after
if (enrollment.userId === currentUser.id) {
rejectEnrollmentInvitation(enrollment.uuid)
} Defensive patterns
Strategy: validation
Validate before calling
if (enrollment.userId !== currentUser.id) {
show('This invitation belongs to a different account — log in as ' + enrollment.userEmail)
return
} Type guard
function isOwnEnrollment(enrollment, user) { return Boolean(user) && enrollment.userId === user.id } Try / catch
try {
await rejectEnrollmentInvitation({ enrollmentUuid })
} catch (e) {
if (e.message.includes('Unauthorized')) show('Log in with the account the invitation was sent to')
else throw e
} Prevention
- Show the invitee email on the action page and warn on account mismatch
- Avoid forwarding authenticated invitation links
- For admin workflows, use admin enrollment APIs instead
- Verify enrollment.user_id matches the session user before mutating
When it happens
Trigger: A logged-in user submits a rejection for someone else's enrollment uuid; shared/forwarded invitation link opened by another account; admin or observer attempting the mutation on behalf of a student.
Common situations: Multiple accounts logged in across browser profiles; forwarding the invitation email to a colleague who is already logged into their own Canvas account; automation using a service account token.
Understand the failure class
Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- Enrollment invitation not found
- Enrollment is not in invited state
- feature flag is disabled
- insufficient permission
- insufficient permission
AI-assisted analysis of instructure/canvas-lms@1c9f0bb801 (2026-09-15).
Data as JSON: /api/errors/c8269fb7b536a137.
Report an issue: GitHub.
Appendix: source
Thrown at app/graphql/mutations/reject_enrollment_invitation.rb:36
# with this program. If not, see <http://www.gnu.org/licenses/>.
#
module Mutations
class RejectEnrollmentInvitation < BaseMutation
argument :enrollment_uuid, String, required: true
field :enrollment, Types::EnrollmentType, null: true
field :success, Boolean, null: false
def resolve(input:, **)
user = context[:current_user]
raise GraphQL::ExecutionError, I18n.t("Must be logged in") unless user
enrollment = Enrollment.where(uuid: input[:enrollment_uuid]).first
raise GraphQL::ExecutionError, I18n.t("Enrollment invitation not found") unless enrollment
# Verify the enrollment belongs to the current user
raise GraphQL::ExecutionError, I18n.t("Unauthorized") unless enrollment.user == user
# Verify the enrollment is in invited state
raise GraphQL::ExecutionError, I18n.t("Enrollment is not in invited state") unless enrollment.invited?
begin
if enrollment.reject
{
enrollment:,
success: true
}
else
{
enrollment: nil,
success: false,
errors: [{ message: I18n.t("Failed to reject enrollment invitation") }]
}
end
rescue => eView on GitHub (pinned to 1c9f0bb801)