{"record":{"id":"1a98965b98b24cb8","repo":"instructure/canvas-lms","slug":"user-id-blank-unable-to-determine-user-for-assessment","errorCode":null,"errorMessage":"User ID blank - unable to determine user for assessment","messagePattern":"User ID blank - unable to determine user for assessment","errorType":"exception","errorClass":"GraphQL::ExecutionError","httpStatus":null,"severity":"error","filePath":"app/graphql/mutations/save_rubric_assessment.rb","lineNumber":46,"sourceCode":"  argument :submission_id, ID, required: true, prepare: GraphQLHelpers.relay_or_legacy_id_prepare_func(\"Submission\")\n\n  field :rubric_assessment, Types::RubricAssessmentType, null: true\n  field :rubric_association, Types::RubricAssociationType, null: true\n  field :submission, Types::SubmissionType, null: true\n  def resolve(input:)\n    root_account = context[:domain_root_account]\n    submission = Submission.find_by(id: input[:submission_id], root_account:)\n    raise GraphQL::ExecutionError, \"Submission not found\" if submission.nil?\n\n    association = RubricAssociation.find(input[:rubric_association_id])\n    association_object = association.association_object\n\n    assessment = association.rubric_assessments.find(input[:rubric_assessment_id]) if input[:rubric_assessment_id].present?\n\n    # only check if there's no assessment object, since that's the only time\n    # this param matters (find_asset_for_assessment)\n    user_id = assessment.present? ? assessment.user_id : submission.user_id\n    raise GraphQL::ExecutionError, \"User ID blank - unable to determine user for assessment\" if user_id.blank?\n\n    # For a moderated assignment, submitting an assessment claims a grading\n    # slot for the submitting provisional grader (or throws an error if no\n    # slots remain).\n    begin\n      opts = {}\n      provisional = input[:provisional]\n      if provisional\n        opts[:provisional_grader] = current_user\n        if input[:final] && association_object.permits_moderation?(current_user)\n          opts[:final] = true\n        end\n      end\n\n      ensure_adjudication_possible(provisional:, association_object:, grader: current_user) do\n        asset, user = association_object.find_asset_for_assessment(association, user_id, opts)\n        assessment_details = JSON.parse(input[:assessment_details]).with_indifferent_access\n        assessment_type = assessment_details[:assessment_type]","sourceCodeStart":28,"sourceCodeEnd":64,"githubUrl":"https://github.com/instructure/canvas-lms/blob/1c9f0bb8013ed69c4f2efe11fd483025469b7e6c/app/graphql/mutations/save_rubric_assessment.rb#L28-L64","documentation":"The mutation needs a user_id to identify whose work is being assessed: from an existing rubric_assessment if rubric_assessment_id was supplied, otherwise from submission.user_id. It raises \"User ID blank - unable to determine user for assessment\" when that resolved user_id is nil/empty, which would break find_asset_for_assessment.","triggerScenarios":"A submission row with a nil user_id (legacy/anonymous or corrupted data), or an existing assessment whose user_id is blank; passing rubric_assessment_id pointing at an anomalous assessment.","commonSituations":"Anonymous/moderated grading flows where submissions have no user; data migrated from older Canvas versions with null user ids; importing submissions from external tools.","solutions":["Inspect the submission/assessment row: fix or backfill user_id if the data is corrupt.","Pass an explicit rubric_assessment_id only when the assessment actually has a user.","For anonymous grading, confirm the feature path intended for anonymized submissions is used instead."],"exampleFix":"// before\nuser_id = assessment.present? ? assessment.user_id : submission.user_id\nraise GraphQL::ExecutionError, 'User ID blank - unable to determine user for assessment' if user_id.blank?\n// after\nuser_id = assessment.present? ? assessment.user_id : submission.user_id\nif user_id.blank?\n  user_id = submission.original_user_id || submission.user&.id\n  raise GraphQL::ExecutionError, 'User ID blank' if user_id.blank?\nend","handlingStrategy":"validation","validationCode":"// server-side guard before assess\nraise GraphQL::ExecutionError, 'Submission has no user' if submission.user_id.blank? && input[:rubric_assessment_id].blank?","typeGuard":"def assessable_user_id?(submission) submission.user_id.present? end","tryCatchPattern":"try { await saveRubricAssessment(...) } catch (e) { if (e.message.includes('User ID blank')) showError('This submission cannot be assessed (no associated user)') }","preventionTips":["Backfill nil user_id on legacy submissions","Skip rubric assessment for anonymous/external submissions without users","Log submission.user_id anomalies during data migrations"],"tags":["graphql","null-value","rubric","data-integrity"],"backgroundTag":"null-argument","analyzedSha":"1c9f0bb8013ed69c4f2efe11fd483025469b7e6c","analyzedAt":"2026-09-15T20:33:18.891Z","contentChangedAt":"2026-09-15T20:33:18.891Z","schemaVersion":2},"datasetVersion":"2026-09-23T02:17:17.105Z"}