instructure/canvas-lms · error · GraphQL::ExecutionError
Anonymous assignments must be manually posted
Error message
Anonymous assignments must be manually posted
What it means
SetAssignmentPostPolicy rejects `postManually: false` (i.e. automatic posting) when the assignment has anonymous grading enabled, raising the localized message "Anonymous assignments must be manually posted". The library enforces this because auto-releasing grades would unmask anonymous submissions; teachers must post manually once anonymity is handled.
Solutions
- Call the mutation with postManually: true for anonymous assignments.
- Disable anonymous grading on the assignment first if automatic posting is truly required, then set postManually: false.
- Filter bulk scripts: skip assignments where anonymousGrading is true (or anonymous grading is locked after submissions exist).
- Note the related rule: moderated assignments must stay manual until grades are published — handle both conditions in automation.
Example fix
// before
setAssignmentPostPolicy(input: { assignmentId: "7", postManually: false }) // anonymous assignment
// after
setAssignmentPostPolicy(input: { assignmentId: "7", postManually: true })
// or, only when anonymity is off:
// if (!assignment.anonymousGrading) setAssignmentPostPolicy(input: { assignmentId: "7", postManually: false }) Defensive patterns
Strategy: validation
Validate before calling
const a = await client.query({ query: ASSIGNMENT_QUERY, variables: { id: assignmentId } });
const assignment = a?.data?.legacyNode ?? a?.data?.assignment;
if (assignment?.anonymousGrading && postManually === false) {
throw new Error('anonymous assignments must be posted manually');
} Type guard
function canAutoPost(assignment) { return !!assignment && !assignment.anonymousGrading && !(assignment.moderatedGrading && !assignment.gradesPublished); } Try / catch
try {
await client.mutate({ mutation: SET_ASSIGNMENT_POST_POLICY, variables: { assignmentId, postManually } });
} catch (e) {
if (e.graphQLErrors?.some(g => /manually posted/.test(g.message))) {
// fall back to postManually: true and surface the constraint to the user
} else { throw e; }
} Prevention
- Check anonymousGrading before setting postManually: false
- Also handle moderated assignments that are not grades-published
- Centralize post-policy logic so bulk tools respect anonymity rules
- Remember anonymity cannot be disabled once submissions exist in some cases — default to manual posting
When it happens
Trigger: Calling setAssignmentPostPolicy with input.postManually == false on an assignment where anonymous_grading? is true (anonymous discussions, anonymously graded assignments), by a user who does hold manage_grades permission.
Common situations: Trying to switch an anonymous assignment back to automatic posting after enabling anonymity; scripts that uniformly set postManually: false across all assignments in a course; migrating post policies without checking assignment grading anonymity settings.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- A maximum of 50 assessees can be provided at once
- A maximum of 50 assessors can be provided at once
- All ConversationMessages must exist within the same…
- An assignment with that id does not exist
- Anonymous assignments cannot be hidden by section
AI-assisted analysis of instructure/canvas-lms@1c9f0bb801 (2026-09-15).
Data as JSON: /api/errors/3b4e603fcf2dba8d.
Report an issue: GitHub.
Appendix: source
Thrown at app/graphql/mutations/set_assignment_post_policy.rb:42
argument :assignment_id, ID, required: true, prepare: GraphQLHelpers.relay_or_legacy_id_prepare_func("Assignment")
argument :post_comments_at, String, required: false
argument :post_grades_at, String, required: false
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
View on GitHub (pinned to 1c9f0bb801)