instructure/canvas-lms · error · GraphQL::ExecutionError
Moderated assignments must be manually posted until grades…
Error message
Moderated assignments must be manually posted until grades are released
What it means
This is a business-rule error raised by the SetAssignmentPostPolicy GraphQL mutation in Canvas LMS. It blocks an attempt to set post_manually=false (automatic posting) on a moderated assignment whose grades have not yet been published. Moderated grading requires a manual posting workflow so moderator-approved grades are not auto-released before final publication, hence the mutation refuses the request via GraphQL::ExecutionError.
Solutions
- Leave the moderated assignment's post policy as post_manually=true until grades are published, then re-run the mutation after publishing grades
- Check assignment.moderated_grading? and assignment.grades_published? before calling the mutation and skip or defer automatic-posting requests for moderated, unpublished assignments
- If automatic posting is genuinely needed, first publish grades for the assignment (e.g. via ModerationGrades/final grades flow), then set post_manually=false
- If moderated grading was enabled unintentionally, disable moderated_grading on the assignment before changing the post policy
Example fix
// before: unconditional mutation call
setAssignmentPostPolicy(input: { assignmentId: id, postManually: false })
// after: guard client-side against moderated grading
const canAutoPost = !assignment.moderatedGrading || assignment.gradesPublished;
if (canAutoPost) {
setAssignmentPostPolicy(input: { assignmentId: id, postManually: false });
} Defensive patterns
Strategy: validation
Validate before calling
function canAutoPost(assignment) {
if (assignment.anonymousGrading) return false; // different error, but also manual-only
if (assignment.moderatedGrading && !assignment.gradesPublished) return false;
return true;
}
if (postManually === false && !canAutoPost(assignment)) {
throw new Error('Moderated assignments must stay manually posted until grades are released');
} Type guard
const isPostableAssignment = (a) => a != null && typeof a.id !== 'undefined' && !(a.moderatedGrading === true && a.gradesPublished === false);
Try / catch
try {
await setAssignmentPostPolicy({ variables: { assignmentId, postManually } });
} catch (e) {
if (e.message.includes('must be manually posted until grades are released')) {
showBanner('Automatic posting is unavailable for moderated assignments until grades are released.');
} else { throw e; }
} Prevention
- Check moderatedGrading and gradesPublished in the UI before offering the automatic-posting toggle
- Default postManually to true for moderated and anonymous assignments
- After publishing grades, refresh the assignment state before retrying the mutation
- Wrap post-policy mutations in a shared helper that pre-validates assignment constraints
When it happens
Trigger: Calling the setAssignmentPostPolicy mutation with input.post_manually == false when (a) assignment.moderated_grading? is true and (b) assignment.grades_published? is false. Note the same block also raises a different message if assignment.anonymous_grading? is true.
Common situations: UI or integration scripts bulk-configuring post policies across course assignments; a teacher or admin turning on automatic posting for a moderated assignment before clicking 'Release grades'; automation importing assignments with moderated grading enabled and default post_manually=false settings.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Assignments under moderation cannot be hidden before grades…
- Assignments under moderation cannot be hidden by section…
- and cannot be used together
- A course with that id does not exist
- An assignment with that id does not exist
AI-assisted analysis of instructure/canvas-lms@1c9f0bb801 (2026-09-15).
Data as JSON: /api/errors/c6ba2e3232cb8141.
Report an issue: GitHub.
Appendix: source
Thrown at app/graphql/mutations/set_assignment_post_policy.rb:45
argument :post_manually, Boolean, required: true
field :post_policy, Types::PostPolicyType, null: true
def resolve(input:)
begin
assignment = AbstractAssignment.find_assignment_or_peer_review(input[:assignment_id])
course = assignment.context
rescue ActiveRecord::RecordNotFound
raise GraphQL::ExecutionError, "An assignment with that id does not exist"
end
verify_authorized_action!(course, :manage_grades)
if input[:post_manually] == false
raise GraphQL::ExecutionError, I18n.t("Anonymous assignments must be manually posted") if assignment.anonymous_grading?
if assignment.moderated_grading? && !assignment.grades_published?
raise GraphQL::ExecutionError, I18n.t("Moderated assignments must be manually posted until grades are released")
end
end
assignment.ensure_post_policy(post_manually: input[:post_manually])
if Account.site_admin.feature_enabled?(:scheduled_feedback_releases) && input[:post_manually] == true
is_post_params_blank = input[:post_comments_at].blank? && input[:post_grades_at].blank?
if !is_post_params_blank
assignment.post_policy.create_or_update_scheduled_post(input[:post_comments_at], input[:post_grades_at])
elsif assignment.post_policy.scheduled_post && is_post_params_blank
assignment.post_policy.remove_scheduled_post
end
end
{ post_policy: assignment.post_policy }
end
View on GitHub (pinned to 1c9f0bb801)