instructure/canvas-lms · error · GraphQL::ExecutionError
Insufficient permissions
Error message
Insufficient permissions
What it means
DeleteConversationMessages#resolve rejects the entire mutation when the root account has the restrict_student_access feature enabled and (per the check ordering) the caller is not permitted, raising "Insufficient permissions". The flag is intended to block students from destructive conversation operations like deleting messages.
Solutions
- Log in / act as a non-student role (teacher, admin) if deletion of messages is required.
- If deletion should be allowed, have an admin disable the restrict_student_access feature flag on the root account.
- Update the client to hide/disable message deletion UI when the flag is active to avoid the failed call.
- Confirm the current_user's root account matches the one where you expect the flag configured.
Example fix
// before
deleteConversationMessages(input: { ids }) // student, flag on -> error
// after
if (me.isStudent && account.featureFlags.restrict_student_access) {
hideDeleteButton()
} else {
deleteConversationMessages(input: { ids })
} Defensive patterns
Strategy: validation
Validate before calling
if (me.isStudent && rootAccount.featureFlags?.restrict_student_access) {
throw new SkipError('message deletion blocked by restrict_student_access')
} Type guard
function canDeleteMessages(me, account) { return !(me.isStudent && account?.featureFlags?.includes('restrict_student_access')); } Try / catch
try {
await deleteConversationMessages({ ids })
} catch (e) {
if (e.message === 'Insufficient permissions') {
disableConversationDeleteUi();
} else throw e;
} Prevention
- Gate conversation delete UI on the user's role and the restrict_student_access flag.
- Only offer destructive conversation actions to teachers/admins where policy requires.
- Document the flag's effect for institutions deploying it.
When it happens
Trigger: A student (or a session without the required role) calling deleteConversationMessages on a root account where restrict_student_access is enabled.
Common situations: Institutions that turn on restrict_student_access to lock down student messaging; K-12/self-service accounts; a client that previously worked before the institution enabled the flag; admins testing with a student masquerade off/on incorrectly.
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
- custom gradebook statuses feature flag is disabled
- feature flag is disabled
- Insufficient permissions
- peer_review_allocation_and_grading feature flag is not…
- ActiveRecord::RecordNotFound
AI-assisted analysis of instructure/canvas-lms@1c9f0bb801 (2026-09-15).
Data as JSON: /api/errors/7198c3d56594631d.
Report an issue: GitHub.
Appendix: source
Thrown at app/graphql/mutations/delete_conversation_messages.rb:31
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
# details.
#
# 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::DeleteConversationMessages < Mutations::BaseMutation
graphql_name "DeleteConversationMessages"
# input arguments
argument :ids, [ID], required: true, prepare: GraphQLHelpers.relay_or_legacy_ids_prepare_func("ConversationMessage")
field :conversation_message_ids, [ID], null: false
def resolve(input:)
if current_user.account.root_account.feature_enabled?(:restrict_student_access)
raise GraphQL::ExecutionError, "Insufficient permissions"
end
messages = ConversationMessage.preload(:conversation).find(input[:ids])
if messages.map(&:conversation).uniq.length > 1
raise GraphQL::ExecutionError, "All ConversationMessages must exist within the same Conversation"
end
participant_record = current_user.all_conversations.find_by(conversation_id: messages.first.conversation.id)
raise GraphQL::ExecutionError, "Insufficient permissions" if participant_record.nil?
participant_record.remove_messages(*messages)
context[:deleted_models] = { conversation_messages: {} }
messages.each { |message| context[:deleted_models][:conversation_messages][message.id.to_s] = message }
{ conversation_message_ids: input[:ids] }
rescue ActiveRecord::RecordInvalid => e
errors_for(e.record)
rescue ActiveRecord::RecordNotFound
raise GraphQL::ExecutionError, "Unable to find ConversationMessage"View on GitHub (pinned to 1c9f0bb801)