diff --git a/app/controllers/admin/watched_words_controller.rb b/app/controllers/admin/watched_words_controller.rb
index 534732d1d5d..a9b3a490c24 100644
--- a/app/controllers/admin/watched_words_controller.rb
+++ b/app/controllers/admin/watched_words_controller.rb
@@ -16,8 +16,9 @@ class Admin::WatchedWordsController < Admin::AdminController
   end
 
   def destroy
-    watched_word = WatchedWord.find(params[:id])
-    watched_word.destroy
+    watched_word = WatchedWord.find_by(id: params[:id])
+    raise Discourse::InvalidParameters.new(:id) unless watched_word
+    watched_word.destroy!
     render json: success_json
   end
 
diff --git a/spec/integration/watched_words_spec.rb b/spec/integration/watched_words_spec.rb
index 2569247e12a..68a7c2c05c0 100644
--- a/spec/integration/watched_words_spec.rb
+++ b/spec/integration/watched_words_spec.rb
@@ -181,25 +181,4 @@ describe WatchedWord do
       }.to_not change { PostAction.count }
     end
   end
-
-  describe 'upload' do
-    context 'logged in as admin' do
-      before do
-        sign_in(admin)
-      end
-
-      it 'creates the words from the file' do
-        post '/admin/logs/watched_words/upload.json', params: {
-          action_key: 'flag',
-          file: Rack::Test::UploadedFile.new(file_from_fixtures("words.csv", "csv"))
-        }
-        expect(response.status).to eq(200)
-        expect(WatchedWord.count).to eq(6)
-        expect(WatchedWord.pluck(:word)).to contain_exactly(
-          'thread', '线', 'धागा', '실', 'tråd', 'нить'
-        )
-        expect(WatchedWord.pluck(:action).uniq).to eq([WatchedWord.actions[:flag]])
-      end
-    end
-  end
 end
diff --git a/spec/requests/admin/watched_words_controller_spec.rb b/spec/requests/admin/watched_words_controller_spec.rb
new file mode 100644
index 00000000000..1b8127c373d
--- /dev/null
+++ b/spec/requests/admin/watched_words_controller_spec.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe Admin::WatchedWordsController do
+  fab!(:admin) { Fabricate(:admin) }
+
+  describe '#destroy' do
+    fab!(:watched_word) { Fabricate(:watched_word) }
+
+    before do
+      sign_in(admin)
+    end
+
+    it 'should return the right response when given an invalid id param' do
+      delete '/admin/logs/watched_words/9999.json'
+
+      expect(response.status).to eq(400)
+    end
+
+    it 'should be able to delete a watched word' do
+      delete "/admin/logs/watched_words/#{watched_word.id}.json"
+
+      expect(response.status).to eq(200)
+      expect(WatchedWord.find_by(id: watched_word.id)).to eq(nil)
+    end
+  end
+
+  describe '#upload' do
+    context 'logged in as admin' do
+      before do
+        sign_in(admin)
+      end
+
+      it 'creates the words from the file' do
+        post '/admin/logs/watched_words/upload.json', params: {
+          action_key: 'flag',
+          file: Rack::Test::UploadedFile.new(file_from_fixtures("words.csv", "csv"))
+        }
+
+        expect(response.status).to eq(200)
+        expect(WatchedWord.count).to eq(6)
+
+        expect(WatchedWord.pluck(:word)).to contain_exactly(
+          'thread', '线', 'धागा', '실', 'tråd', 'нить'
+        )
+
+        expect(WatchedWord.pluck(:action).uniq).to eq([WatchedWord.actions[:flag]])
+      end
+    end
+  end
+end