instructure/canvas-lms · error · GraphQL::ExecutionError
Enrollment invitation not found
Error message
Enrollment invitation not found
What it means
Raised when no Enrollment record matches the supplied enrollment_uuid. The mutation looks up Enrollment.where(uuid: input[:enrollment_uuid]).first and raises this error when the lookup returns nil, so the invitation cannot be rejected.
Solutions
- Verify the uuid corresponds to an existing Enrollment via Enrollment.where(uuid: ...).exists?
- Re-send/refresh the invitation link to get the current enrollment uuid
- Handle the already-processed case in the UI instead of re-invoking the mutation
- Confirm you are hitting the correct Canvas environment/shard
Example fix
// before rejectEnrollmentInvitation(courseUuid) // after rejectEnrollmentInvitation(enrollmentUuid) // Enrollment.find_by(uuid: enrollmentUuid)&.uuid
Defensive patterns
Strategy: validation
Validate before calling
const enrollment = await fetchEnrollmentByUuid(uuid)
if (!enrollment) show('Invitation no longer valid') Type guard
function isEnrollment(e) { return e != null && typeof e.uuid === 'string' && e.workflowState != null } Try / catch
try {
await rejectEnrollmentInvitation({ enrollmentUuid })
} catch (e) {
if (e.message.includes('Enrollment invitation not found')) {
show('This invitation has expired or was already processed'); refetchState()
} else throw e
} Prevention
- Pass the enrollment uuid, not course/user uuid
- Re-fetch the invitation link server-side before rendering the decline action
- Treat 'not found' as already-processed in idempotent UI flows
- Confirm you are in the correct environment/shard
When it happens
Trigger: Passing a UUID that is not an enrollment uuid (e.g. the course uuid or a user uuid); the enrollment was already accepted/rejected/deleted and purged; typo or truncated uuid; querying on the wrong shard/root account.
Common situations: Stale email links after the enrollment was re-created (regenerated uuid); user clicks 'decline' twice; uuid copied from a different environment (test vs production).
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
- Allocation rule not found
- Assignment not found
- assignment not found: #
- assignment not found
- custom grade status not found
AI-assisted analysis of instructure/canvas-lms@1c9f0bb801 (2026-09-15).
Data as JSON: /api/errors/2969ce8bc6462785.
Report an issue: GitHub.
Appendix: source
Thrown at app/graphql/mutations/reject_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 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") }]View on GitHub (pinned to 1c9f0bb801)