diff --git a/app/assets/javascripts/discourse/app/form-kit/lib/validation-parser.js b/app/assets/javascripts/discourse/app/form-kit/lib/validation-parser.js
index e62ff51f0ce..11206ef0b58 100644
--- a/app/assets/javascripts/discourse/app/form-kit/lib/validation-parser.js
+++ b/app/assets/javascripts/discourse/app/form-kit/lib/validation-parser.js
@@ -11,7 +11,7 @@ export default class ValidationParser {
       if (this[ruleName + "Rule"]) {
         rules[ruleName] = this[ruleName + "Rule"](args);
       } else {
-        throw new Error(`Unknown rule: ${ruleName}`);
+        rules[ruleName] = {};
       }
     });
 
@@ -25,18 +25,6 @@ export default class ValidationParser {
     };
   }
 
-  urlRule() {
-    return {};
-  }
-
-  acceptedRule() {
-    return {};
-  }
-
-  numberRule() {
-    return {};
-  }
-
   betweenRule(args) {
     if (!args) {
       throw new Error("`between` rule expects min/max, eg: between:1,10");
diff --git a/app/assets/javascripts/discourse/app/form-kit/lib/validator.js b/app/assets/javascripts/discourse/app/form-kit/lib/validator.js
index c08d615da6a..58e2d6ae131 100644
--- a/app/assets/javascripts/discourse/app/form-kit/lib/validator.js
+++ b/app/assets/javascripts/discourse/app/form-kit/lib/validator.js
@@ -27,6 +27,12 @@ export default class Validator {
     return errors;
   }
 
+  integerValidator(value) {
+    if (!Number.isInteger(Number(value))) {
+      return I18n.t("form_kit.errors.not_an_integer");
+    }
+  }
+
   lengthValidator(value, rule) {
     if (rule.max) {
       if (value?.length > rule.max) {
diff --git a/app/assets/javascripts/discourse/tests/unit/lib/form-kit/validation-parser-test.js b/app/assets/javascripts/discourse/tests/unit/lib/form-kit/validation-parser-test.js
index 27e5e3d5814..a496f2c31fe 100644
--- a/app/assets/javascripts/discourse/tests/unit/lib/form-kit/validation-parser-test.js
+++ b/app/assets/javascripts/discourse/tests/unit/lib/form-kit/validation-parser-test.js
@@ -12,10 +12,6 @@ module("Unit | Lib | FormKit | ValidationParser", function (hooks) {
     assert.deepEqual(rules.url, {});
   });
 
-  test("unknown rule", function (assert) {
-    assert.throws(() => ValidationParser.parse("foo"), "Unknown rule: foo");
-  });
-
   test("required", function (assert) {
     const rules = ValidationParser.parse("required");
 
diff --git a/app/assets/javascripts/discourse/tests/unit/lib/form-kit/validator-test.js b/app/assets/javascripts/discourse/tests/unit/lib/form-kit/validator-test.js
index 304bd9c14ff..052a63db5bd 100644
--- a/app/assets/javascripts/discourse/tests/unit/lib/form-kit/validator-test.js
+++ b/app/assets/javascripts/discourse/tests/unit/lib/form-kit/validator-test.js
@@ -92,6 +92,25 @@ module("Unit | Lib | FormKit | Validator", function (hooks) {
     );
   });
 
+  test("integer", async function (assert) {
+    let errors = await new Validator(1.2, {
+      integer: {},
+    }).validate();
+
+    assert.deepEqual(
+      errors,
+      [I18n.t("form_kit.errors.not_an_integer")],
+      "it returns an error when the value is not an integer"
+    );
+
+    errors = await new Validator(1, { integer: {} }).validate();
+    assert.deepEqual(
+      errors,
+      [],
+      "it returns no errors when the value is an integer"
+    );
+  });
+
   test("number", async function (assert) {
     let errors = await new Validator("A", {
       number: {},
diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml
index ff700b26582..aa8cf0d9ddc 100644
--- a/config/locales/client.en.yml
+++ b/config/locales/client.en.yml
@@ -2105,6 +2105,7 @@ en:
       errors:
         required: "Required"
         invalid_url: "Must be a valid URL"
+        not_an_integer: "Must be an integer"
         not_accepted: "Must be accepted"
         not_a_number: "Must be a number"
         too_high: "Must be at most %{count}"