instructure/canvas-lms · error · GraphQL::ExecutionError
Enrollment invitation not found
Error message
Enrollment invitation not found
What it means
AcceptEnrollmentInvitation looks up the enrollment by the provided enrollment_uuid (Enrollment.where(uuid: input[:enrollment_uuid]).first) and raises 'Enrollment invitation not found' when no enrollment matches. The uuid is a per-invitation identifier, so any typo, stale link, or deleted/merged enrollment leads here.
Solutions
- Verify the exact enrollment_uuid string from the invitation (no truncation/whitespace) and retry.
- Re-issue the invitation so a fresh enrollment/uuid is generated, then accept that.
- Confirm you are hitting the same environment/shard where the enrollment was created.
- Check the enrollment still exists: find by uuid in the Rails console (Enrollment.find_by(uuid: ...)).
- Handle nil in client code and surface 'invitation no longer valid' to the user with a path to re-invite.
Example fix
// before
const enrollment = await Enrollment.findOne({ where: { uuid: suppliedUuid } })
if (!enrollment) throw new Error("Enrollment invitation not found")
// after
const enrollment = await Enrollment.findOne({ where: { uuid: normalizeUuid(suppliedUuid) } })
if (!enrollment) return { success: false, reason: "invitation_invalid_or_expired" } // re-invite flow Defensive patterns
Strategy: validation
Validate before calling
// validate uuid shape and presence before the call
const UUID_RE = /^[0-9a-f]{32}$/i // Canvas uuids (adjust per format)
if (!UUID_RE.test((enrollmentUuid || "").trim()))
throw new Error("invalid enrollment_uuid; copy it from the invitation link exactly") Try / catch
try {
await client.request(ACCEPT_INVITATION, { enrollmentUuid })
} catch (e) {
if (/Enrollment invitation not found/.test(e.message))
return showInvitationExpiredScreen() // offer re-invite
throw e
} Prevention
- Copy uuids verbatim from invitation links (no truncation)
- Don't reuse uuids across environments
- Handle revoked/expired invitations with a re-invite path
- Verify enrollment existence in console when debugging
When it happens
Trigger: Mutation called with an enrollment_uuid that does not exist: truncated/copy-paste-damaged uuid from an invitation email, invitation revoked and enrollment deleted, uuid from a different shard/ENV, or a fabricated id.
Common situations: Users clicking old invitation emails after the course was concluded and enrollments purged; test fixtures reusing uuids across environments (test vs production DB); self-registration tools storing uuids before enrollment creation completes.
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
- All ConversationMessages must exist within the same…
- Allocation rule not found
- An unexpected error occurred while grading.
- An unexpected error occurred while submitting feedback.
- Assignment not found
AI-assisted analysis of instructure/canvas-lms@1c9f0bb801 (2026-09-15).
Data as JSON: /api/errors/899145d2d2b22866.
Report an issue: GitHub.
Appendix: source
Thrown at app/graphql/mutations/accept_enrollment_invitation.rb:33
# details.
#
# You should have received a copy of the GNU Affero General Public License along
# with this program. If not, see <http://www.gnu.org/licenses/>.
#
module Mutations
class AcceptEnrollmentInvitation < 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.accept!
{
enrollment:,
success: true
}
else
{
enrollment: nil,
success: false,
errors: [{ message: I18n.t("Failed to accept enrollment invitation") }]View on GitHub (pinned to 1c9f0bb801)