instructure/canvas-lms · error · GraphQL::ExecutionError
insufficient permission
Error message
insufficient permission
What it means
UpdateDiscussionTopicParticipant#resolve raises "insufficient permission" when the topic exists but does not grant :read to the current user; the trailing rescue separately turns RecordNotFound into "not found". Participants (read state, entries count, summary prefs) can only be updated on readable topics.
Solutions
- Pre-check discussion_topic.grants_right?(current_user, session, :read) before the mutation.
- Ensure the API token/session belongs to an enrolled, active user.
- Delay participant updates until the topic becomes available to that role.
- Fix section-limited enrollments if the user should have access.
Example fix
// before
updateDiscussionTopicParticipant(input: {discussionTopicId: t, read: true})
// after
if (topicPermissions.read) {
updateDiscussionTopicParticipant(input: {discussionTopicId: t, read: true})
} Defensive patterns
Strategy: type-guard
Validate before calling
query { discussionTopic(id: $id) { permissions { read } } }
if (!data.discussionTopic?.permissions?.read) return; Type guard
function canReadTopic(t) { return t?.permissions?.read === true; } Try / catch
try {
await updateDiscussionTopicParticipant(...);
} catch (e) {
if (['not found', 'insufficient permission'].includes(e.message)) stopParticipantSync();
else throw e;
} Prevention
- Check topic availability dates before participant updates
- Use the enrolled user's own token for read-state sync jobs
- Treat not-found and permission errors identically to avoid leaking topic existence
- Re-verify enrollment after course section changes
When it happens
Trigger: updateDiscussionTopicParticipant with discussion_topic_id of an unpublished/delayed topic for a student, a topic in a course the token user is not enrolled in, or with a nil/invalid session causing grants_right? to fail.
Common situations: Background unread-count sync running before enrollment activation; mobile app tokens tied to a stale user; observers restricted by section limitation; announcements in read-only public courses.
Understand the failure class
Background: "You do not have permission" / 403 Forbidden errors: authenticated but not allowed — causes and fixes across open-source libraries — this error's family across 31 libraries.
Related errors
- Insufficient Permissions
- not found
- not found
- ActiveRecord::RecordNotFound
- Cannot set rubric self assessment for discussion assignments
AI-assisted analysis of instructure/canvas-lms@1c9f0bb801 (2026-09-15).
Data as JSON: /api/errors/73dedfd58928189b.
Report an issue: GitHub.
Appendix: source
Thrown at app/graphql/mutations/update_discussion_topic_participant.rb:35
# 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/>.
#
class Mutations::UpdateDiscussionTopicParticipant < Mutations::BaseMutation
graphql_name "UpdateDiscussionTopicParticipant"
argument :discussion_topic_id, ID, required: true, prepare: GraphQLHelpers.relay_or_legacy_id_prepare_func("DiscussionEntry")
argument :expanded, Boolean, required: false
argument :has_unread_pinned_entry, Boolean, required: false
argument :preferred_language, Types::PreferredLanguageType, required: false
argument :show_pinned_entries, Boolean, required: false
argument :sort_order, Types::DiscussionSortOrderType, required: false
argument :summary_enabled, Boolean, required: false
field :discussion_topic, Types::DiscussionType, null: false
def resolve(input:)
discussion_topic = DiscussionTopic.find(input[:discussion_topic_id])
raise GraphQL::ExecutionError, "insufficient permission" unless discussion_topic.grants_right?(current_user, session, :read)
discussion_topic.update_or_create_participant(current_user:, **input)
{ discussion_topic: }
rescue ActiveRecord::RecordNotFound
raise GraphQL::ExecutionError, "not found"
end
end
View on GitHub (pinned to 1c9f0bb801)