instructure/canvas-lms · error · GraphQL::ExecutionError

Unable to delete CommentBankItem

Error message

Unable to delete CommentBankItem

What it means

After authorization succeeds, DeleteCommentBankItem calls record.destroy; if destroy returns false (the model refused to delete, typically due to a before_destroy callback aborting or validation-adjacent failure), the mutation raises "Unable to delete CommentBankItem". Unlike the not-found case, the record exists but could not be removed.

Solutions

  1. Check CommentBankItem model callbacks (before_destroy) for abort conditions and logs for the actual reason.
  2. Retry the deletion; transient DB issues can make destroy return false.
  3. Inspect Rails logs around the mutation for suppressed errors during destroy.
  4. As an admin, verify no shard/replica lag is causing the record state to conflict.

Example fix

// before
if record.destroy
  { comment_bank_item_id: record.id }
else
  raise GraphQL::ExecutionError, "Unable to delete CommentBankItem"
end
// after
if record.destroy
  { comment_bank_item_id: record.id }
else
  raise GraphQL::ExecutionError, record.errors.full_messages.to_sentence.presence || "Unable to delete CommentBankItem"
end
Defensive patterns

Strategy: try-catch

Try / catch

try {
  await deleteCommentBankItem({ id })
} catch (e) {
  if (e.message.includes('Unable to delete CommentBankItem')) {
    retryWithBackoff(() => deleteCommentBankItem({ id }))
      .catch(() => reportServerError('comment bank delete failed'));
  } else throw e;
}

Prevention

When it happens

Trigger: Calling deleteCommentBankItem on an item whose destroy callback aborts; database constraint or hook preventing deletion; concurrent modification making destroy fail.

Common situations: Item referenced elsewhere and a before_destroy guard aborts; DB replication/constraint issue; plugin or shard-level callback raising silently and returning false.

Related errors


AI-assisted analysis of instructure/canvas-lms@1c9f0bb801 (2026-09-15). Data as JSON: /api/errors/91aa632da5f30a97. Report an issue: GitHub.

Appendix: source

Thrown at app/graphql/mutations/delete_comment_bank_item.rb:37

#

class Mutations::DeleteCommentBankItem < Mutations::BaseMutation
  graphql_name "DeleteCommentBankItem"

  argument :id, ID, required: true, prepare: GraphQLHelpers.relay_or_legacy_id_prepare_func("CommentBankItem")
  field :comment_bank_item_id, ID, null: false

  def resolve(input:)
    record = CommentBankItem.active.find_by(id: input[:id])
    raise GraphQL::ExecutionError, I18n.t("Unable to find CommentBankItem") if record.nil?

    verify_authorized_action!(record, :delete)
    context[:deleted_models][:comment_bank_item] = record

    if record.destroy
      { comment_bank_item_id: record.id }
    else
      raise GraphQL::ExecutionError, I18n.t("Unable to delete CommentBankItem")
    end
  end

  def self.comment_bank_item_id_log_entry(_entry, context)
    context[:deleted_models][:comment_bank_item]
  end
end

View on GitHub (pinned to 1c9f0bb801)