diff --git a/src/Ruleset.php b/src/Ruleset.php
index 57e10e8464..95446e6254 100644
--- a/src/Ruleset.php
+++ b/src/Ruleset.php
@@ -1409,7 +1409,12 @@ public function registerSniffs($files, $restrictions, $exclusions)
continue;
}
- if ($reflection->implementsInterface('PHP_CodeSniffer\Sniffs\Sniff') === false) {
+ if ($reflection->implementsInterface('PHP_CodeSniffer\\Sniffs\\Sniff') === false) {
+ $message = 'All sniffs must implement the PHP_CodeSniffer\\Sniffs\\Sniff interface.'.PHP_EOL;
+ $message .= "Interface not implemented for sniff $className.".PHP_EOL;
+ $message .= 'Contact the sniff author to fix the sniff.';
+ $this->msgCache->add($message, MessageCollector::DEPRECATED);
+
// Skip classes which don't implement the register() or process() methods.
if (method_exists($className, 'register') === false
|| method_exists($className, 'process') === false
diff --git a/tests/Core/Ruleset/Fixtures/TestStandard/Sniffs/MissingInterface/InvalidImplementsWithoutImplementSniff.php b/tests/Core/Ruleset/Fixtures/TestStandard/Sniffs/MissingInterface/InvalidImplementsWithoutImplementSniff.php
new file mode 100644
index 0000000000..39e61e385a
--- /dev/null
+++ b/tests/Core/Ruleset/Fixtures/TestStandard/Sniffs/MissingInterface/InvalidImplementsWithoutImplementSniff.php
@@ -0,0 +1,24 @@
+
+
diff --git a/tests/Core/Ruleset/ProcessRulesetTest.php b/tests/Core/Ruleset/ProcessRulesetTest.php
index fa704bef51..d37c031021 100644
--- a/tests/Core/Ruleset/ProcessRulesetTest.php
+++ b/tests/Core/Ruleset/ProcessRulesetTest.php
@@ -67,6 +67,8 @@ public function testAutoExpandSniffsDirectory()
"$std.DeprecatedInvalid.InvalidDeprecationMessage" => "$sniffDir\DeprecatedInvalid\InvalidDeprecationMessageSniff",
"$std.DeprecatedInvalid.InvalidDeprecationVersion" => "$sniffDir\DeprecatedInvalid\InvalidDeprecationVersionSniff",
"$std.DeprecatedInvalid.InvalidRemovalVersion" => "$sniffDir\DeprecatedInvalid\InvalidRemovalVersionSniff",
+ "$std.MissingInterface.ValidImplements" => "$sniffDir\MissingInterface\ValidImplementsSniff",
+ "$std.MissingInterface.ValidImplementsViaAbstract" => "$sniffDir\MissingInterface\ValidImplementsViaAbstractSniff",
"$std.SetProperty.AllowedAsDeclared" => "$sniffDir\SetProperty\AllowedAsDeclaredSniff",
"$std.SetProperty.AllowedViaMagicMethod" => "$sniffDir\SetProperty\AllowedViaMagicMethodSniff",
"$std.SetProperty.AllowedViaStdClass" => "$sniffDir\SetProperty\AllowedViaStdClassSniff",
diff --git a/tests/Core/Ruleset/RegisterSniffsMissingInterfaceInvalidTest.xml b/tests/Core/Ruleset/RegisterSniffsMissingInterfaceInvalidTest.xml
new file mode 100644
index 0000000000..52b264f07e
--- /dev/null
+++ b/tests/Core/Ruleset/RegisterSniffsMissingInterfaceInvalidTest.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/tests/Core/Ruleset/RegisterSniffsMissingInterfaceTest.php b/tests/Core/Ruleset/RegisterSniffsMissingInterfaceTest.php
new file mode 100644
index 0000000000..89c82c028a
--- /dev/null
+++ b/tests/Core/Ruleset/RegisterSniffsMissingInterfaceTest.php
@@ -0,0 +1,65 @@
+
+ * @copyright 2025 PHPCSStandards and contributors
+ * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
+ */
+
+namespace PHP_CodeSniffer\Tests\Core\Ruleset;
+
+use PHP_CodeSniffer\Ruleset;
+use PHP_CodeSniffer\Tests\ConfigDouble;
+use PHPUnit\Framework\TestCase;
+
+/**
+ * Tests deprecation of support for sniffs not implementing the PHPCS `Sniff` interface.
+ *
+ * @covers \PHP_CodeSniffer\Ruleset::registerSniffs
+ */
+final class RegisterSniffsMissingInterfaceTest extends TestCase
+{
+
+
+ /**
+ * Test that no deprecation is shown when sniffs implement the `PHP_CodeSniffer\Sniffs\Sniff` interface.
+ *
+ * @return void
+ */
+ public function testNoNoticesForSniffsImplementingInterface()
+ {
+ // Set up the ruleset.
+ $standard = __DIR__.'/RegisterSniffsMissingInterfaceValidTest.xml';
+ $config = new ConfigDouble(["--standard=$standard"]);
+
+ $this->expectOutputString('');
+
+ new Ruleset($config);
+
+ }//end testNoNoticesForSniffsImplementingInterface()
+
+
+ /**
+ * Test that a deprecation notice is shown if a sniff doesn't implement the Sniff interface.
+ *
+ * @return void
+ */
+ public function testDeprecationNoticeWhenSniffDoesntImplementInterface()
+ {
+ // Set up the ruleset.
+ $standard = __DIR__.'/RegisterSniffsMissingInterfaceInvalidTest.xml';
+ $config = new ConfigDouble(["--standard=$standard"]);
+
+ $expected = 'DEPRECATED: All sniffs must implement the PHP_CodeSniffer\\Sniffs\\Sniff interface.'.PHP_EOL;
+ $expected .= 'Interface not implemented for sniff Fixtures\\TestStandard\\Sniffs\\MissingInterface\\InvalidImplementsWithoutImplementSniff.'.PHP_EOL;
+ $expected .= 'Contact the sniff author to fix the sniff.'.PHP_EOL.PHP_EOL;
+
+ $this->expectOutputString($expected);
+
+ new Ruleset($config);
+
+ }//end testDeprecationNoticeWhenSniffDoesntImplementInterface()
+
+
+}//end class
diff --git a/tests/Core/Ruleset/RegisterSniffsMissingInterfaceValidTest.xml b/tests/Core/Ruleset/RegisterSniffsMissingInterfaceValidTest.xml
new file mode 100644
index 0000000000..39de8d4224
--- /dev/null
+++ b/tests/Core/Ruleset/RegisterSniffsMissingInterfaceValidTest.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
diff --git a/tests/Core/Ruleset/ShowSniffDeprecationsTest.xml b/tests/Core/Ruleset/ShowSniffDeprecationsTest.xml
index ab632b1959..4cfecfe79f 100644
--- a/tests/Core/Ruleset/ShowSniffDeprecationsTest.xml
+++ b/tests/Core/Ruleset/ShowSniffDeprecationsTest.xml
@@ -7,6 +7,7 @@
+