{"record":{"id":"326e2907c64be349","repo":"instructure/canvas-lms","slug":"assignments-under-moderation-cannot-be-hidden-by-section","errorCode":null,"errorMessage":"Assignments under moderation cannot be hidden by section before grades are published","messagePattern":"Assignments under moderation cannot be hidden by section before grades are published","errorType":"exception","errorClass":"GraphQL::ExecutionError","httpStatus":null,"severity":"error","filePath":"app/graphql/mutations/hide_assignment_grades_for_sections.rb","lineNumber":43,"sourceCode":"  argument :section_ids, [ID], required: true, prepare: GraphQLHelpers.relay_or_legacy_ids_prepare_func(\"Section\")\n\n  field :assignment, Types::AssignmentType, null: true\n  field :progress, Types::ProgressType, null: true\n  field :sections, [Types::SectionType], null: true\n\n  def resolve(input:)\n    begin\n      assignment = AbstractAssignment.find_assignment_or_peer_review(input[:assignment_id])\n      course = assignment.context\n      sections = course.course_sections.where(id: input[:section_ids])\n    rescue ActiveRecord::RecordNotFound\n      raise GraphQL::ExecutionError, \"not found\"\n    end\n\n    verify_authorized_action!(assignment, :grade)\n\n    unless assignment.grades_published?\n      raise GraphQL::ExecutionError, \"Assignments under moderation cannot be hidden by section before grades are published\"\n    end\n    raise GraphQL::ExecutionError, \"Anonymous assignments cannot be hidden by section\" if assignment.anonymize_students?\n\n    if sections.empty? || sections.count != input[:section_ids].size\n      raise GraphQL::ExecutionError, \"Invalid section ids\"\n    end\n\n    visible_enrollments = course.apply_enrollment_visibility(course.student_enrollments, current_user, sections)\n\n    submissions_scope = input[:graded_only] ? assignment.submissions.graded : assignment.submissions\n    submissions_scope = submissions_scope.joins(user: :enrollments).merge(visible_enrollments)\n\n    progress = course.progresses.new(tag: \"hide_assignment_grades_for_sections\")\n\n    if progress.save\n      progress.process_job(\n        assignment,\n        :hide_submissions,","sourceCodeStart":25,"sourceCodeEnd":61,"githubUrl":"https://github.com/instructure/canvas-lms/blob/1c9f0bb8013ed69c4f2efe11fd483025469b7e6c/app/graphql/mutations/hide_assignment_grades_for_sections.rb#L25-L61","documentation":"Section-based hiding is forbidden on assignments still under moderated grading whose grades have not been published (grades_published? false), mirroring the general mutation but with a section-specific message. Provisional grades must be finalized before any section-scoped posting/hide operation.","triggerScenarios":"Calling hideAssignmentGradesForSections for an assignment with moderated_grading enabled before the moderator publishes final grades.","commonSituations":"Departmental workflows where different sections are moderated independently and a teacher assumes their section is done; scheduled scripts hiding grades by section after term end without checking publication state.","solutions":["Have a moderator publish grades for the assignment first (grades_published!), then retry the section hide.","Check grades_published_at / gradesPublished via GraphQL before calling and block the action in the UI.","If moderated grading is unnecessary, disable it before grading begins.","Coordinate with the moderation workflow (moderation setters) rather than bypassing with direct DB updates."],"exampleFix":"// before\nawait HideBySection.mutate({ assignmentId, sectionIds });\n// after\nconst a = await fetchAssignment(assignmentId);\nif (a.moderatedGrading && !a.gradesPublished) {\n  notifyModerator(assignmentId);\n  return; // wait for publish\n}\nawait HideBySection.mutate({ assignmentId, sectionIds });","handlingStrategy":"validation","validationCode":"const a = await fetchAssignment(assignmentId);\nif (a.moderatedGrading && !a.gradesPublished) throw new SkipError('Grades not published yet');","typeGuard":"const sectionHideAllowed = (a) => Boolean(a && a.gradesPublished === true);","tryCatchPattern":"try { await hideBySection({ assignmentId, sectionIds }); }\ncatch (e) {\n  if (String(e).includes('grades are published')) { await notifyModerator(assignmentId); return; }\n  throw e;\n}","preventionTips":["Gate section-hide UI on gradesPublished","Align automation with the moderation workflow timelines","Check assignment.moderatedGrading flag in queries","Educate graders that only moderators publish final grades"],"tags":["graphql","moderated-grading","canvas-lms"],"backgroundTag":"invalid-state-transition","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"}