diff --git a/CHANGELOG.md b/CHANGELOG.md
index e9c2a373..bc7829aa 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
 
 For a full diff see [`2.4.0...main`][2.4.0...main].
 
+### Added
+
+- Added rule error identifiers ([#875]), by [@localheinz]
+
 ## [`2.4.0`][2.4.0]
 
 For a full diff see [`2.3.0...2.4.0`][2.3.0...2.4.0].
@@ -523,6 +527,7 @@ For a full diff see [`362c7ea...0.1.0`][362c7ea...0.1.0].
 [#735]: https://github.com/ergebnis/phpstan-rules/pull/735
 [#862]: https://github.com/ergebnis/phpstan-rules/pull/862
 [#872]: https://github.com/ergebnis/phpstan-rules/pull/872
+[#875]: https://github.com/ergebnis/phpstan-rules/pull/875
 
 [@enumag]: https://github.com/enumag
 [@ergebnis]: https://github.com/ergebnis
diff --git a/src/Classes/FinalRule.php b/src/Classes/FinalRule.php
index 22c85c45..f45d8966 100644
--- a/src/Classes/FinalRule.php
+++ b/src/Classes/FinalRule.php
@@ -107,10 +107,15 @@ public function processNode(
         ));
 
         return [
-            $ruleErrorBuilder->build(),
+            $ruleErrorBuilder->identifier(self::identifier())->build(),
         ];
     }
 
+    private static function identifier(): string
+    {
+        return 'ergebnis.final';
+    }
+
     /**
      * This method is inspired by the work on PhpCsFixer\Fixer\ClassNotation\FinalClassFixer and
      * PhpCsFixer\Fixer\ClassNotation\FinalInternalClassFixer contributed by Dariusz RumiƄski, Filippo Tessarotto, and
diff --git a/src/Classes/NoExtendsRule.php b/src/Classes/NoExtendsRule.php
index 77d1cace..a711cfa6 100644
--- a/src/Classes/NoExtendsRule.php
+++ b/src/Classes/NoExtendsRule.php
@@ -83,7 +83,7 @@ public function processNode(
             ));
 
             return [
-                $ruleErrorBuilder->build(),
+                $ruleErrorBuilder->identifier(self::identifier())->build(),
             ];
         }
 
@@ -94,7 +94,12 @@ public function processNode(
         ));
 
         return [
-            $ruleErrorBuilder->build(),
+            $ruleErrorBuilder->identifier(self::identifier())->build(),
         ];
     }
+
+    private static function identifier(): string
+    {
+        return 'ergebnis.noExtends';
+    }
 }
diff --git a/src/Classes/PHPUnit/Framework/TestCaseWithSuffixRule.php b/src/Classes/PHPUnit/Framework/TestCaseWithSuffixRule.php
index ff00d4b9..3fdf407e 100644
--- a/src/Classes/PHPUnit/Framework/TestCaseWithSuffixRule.php
+++ b/src/Classes/PHPUnit/Framework/TestCaseWithSuffixRule.php
@@ -96,7 +96,12 @@ public function processNode(
         ));
 
         return [
-            $ruleErrorBuilder->build(),
+            $ruleErrorBuilder->identifier(self::identifier())->build(),
         ];
     }
+
+    private static function identifier(): string
+    {
+        return 'ergebnis.classes.phpunit.framework.testCaseWithSuffix';
+    }
 }
diff --git a/src/Closures/NoNullableReturnTypeDeclarationRule.php b/src/Closures/NoNullableReturnTypeDeclarationRule.php
index 67bfbc0a..f63c37c6 100644
--- a/src/Closures/NoNullableReturnTypeDeclarationRule.php
+++ b/src/Closures/NoNullableReturnTypeDeclarationRule.php
@@ -47,7 +47,7 @@ public function processNode(
         $ruleErrorBuilder = Rules\RuleErrorBuilder::message('Closure has a nullable return type declaration.');
 
         return [
-            $ruleErrorBuilder->build(),
+            $ruleErrorBuilder->identifier(self::identifier())->build(),
         ];
     }
 
@@ -73,4 +73,9 @@ private static function hasNullableReturnType(Node\Expr\Closure $node): bool
 
         return false;
     }
+
+    private static function identifier(): string
+    {
+        return 'ergebnis.noNullableReturnTypeDeclaration';
+    }
 }
diff --git a/src/Closures/NoParameterWithNullDefaultValueRule.php b/src/Closures/NoParameterWithNullDefaultValueRule.php
index 381f928b..07fcad0f 100644
--- a/src/Closures/NoParameterWithNullDefaultValueRule.php
+++ b/src/Closures/NoParameterWithNullDefaultValueRule.php
@@ -68,7 +68,12 @@ public function processNode(
                 $parameterName,
             ));
 
-            return $ruleErrorBuilder->build();
+            return $ruleErrorBuilder->identifier(self::identifier())->build();
         }, $params);
     }
+
+    private static function identifier(): string
+    {
+        return 'ergebnis.noParameterWithNullDefaultValue';
+    }
 }
diff --git a/src/Closures/NoParameterWithNullableTypeDeclarationRule.php b/src/Closures/NoParameterWithNullableTypeDeclarationRule.php
index 6ba414a4..c2c39f25 100644
--- a/src/Closures/NoParameterWithNullableTypeDeclarationRule.php
+++ b/src/Closures/NoParameterWithNullableTypeDeclarationRule.php
@@ -64,7 +64,7 @@ public function processNode(
                 $parameterName,
             ));
 
-            return $ruleErrorBuilder->build();
+            return $ruleErrorBuilder->identifier(self::identifier())->build();
         }, $params);
     }
 
@@ -90,4 +90,9 @@ private static function isNullable(Node\Param $node): bool
 
         return false;
     }
+
+    private static function identifier(): string
+    {
+        return 'ergebnis.noParameterWithNullableTypeDeclaration';
+    }
 }
diff --git a/src/Expressions/NoCompactRule.php b/src/Expressions/NoCompactRule.php
index 6dcc1462..184b804b 100644
--- a/src/Expressions/NoCompactRule.php
+++ b/src/Expressions/NoCompactRule.php
@@ -51,7 +51,12 @@ public function processNode(
         $ruleErrorBuilder = Rules\RuleErrorBuilder::message('Function compact() should not be used.');
 
         return [
-            $ruleErrorBuilder->build(),
+            $ruleErrorBuilder->identifier(self::identifier())->build(),
         ];
     }
+
+    private static function identifier(): string
+    {
+        return 'ergebnis.noCompact';
+    }
 }
diff --git a/src/Expressions/NoErrorSuppressionRule.php b/src/Expressions/NoErrorSuppressionRule.php
index c945f7e0..1cabf830 100644
--- a/src/Expressions/NoErrorSuppressionRule.php
+++ b/src/Expressions/NoErrorSuppressionRule.php
@@ -34,7 +34,12 @@ public function processNode(
         $ruleErrorBuilder = Rules\RuleErrorBuilder::message('Error suppression via "@" should not be used.');
 
         return [
-            $ruleErrorBuilder->build(),
+            $ruleErrorBuilder->identifier(self::identifier())->build(),
         ];
     }
+
+    private static function identifier(): string
+    {
+        return 'ergebnis.noErrorSuppression';
+    }
 }
diff --git a/src/Expressions/NoEvalRule.php b/src/Expressions/NoEvalRule.php
index 317663dd..be8b3450 100644
--- a/src/Expressions/NoEvalRule.php
+++ b/src/Expressions/NoEvalRule.php
@@ -34,7 +34,12 @@ public function processNode(
         $ruleErrorBuilder = Rules\RuleErrorBuilder::message('Language construct eval() should not be used.');
 
         return [
-            $ruleErrorBuilder->build(),
+            $ruleErrorBuilder->identifier(self::identifier())->build(),
         ];
     }
+
+    private static function identifier(): string
+    {
+        return 'ergebnis.noEval';
+    }
 }
diff --git a/src/Expressions/NoIssetRule.php b/src/Expressions/NoIssetRule.php
index bcba10b5..76fd3612 100644
--- a/src/Expressions/NoIssetRule.php
+++ b/src/Expressions/NoIssetRule.php
@@ -34,7 +34,12 @@ public function processNode(
         $ruleErrorBuilder = Rules\RuleErrorBuilder::message('Language construct isset() should not be used.');
 
         return [
-            $ruleErrorBuilder->build(),
+            $ruleErrorBuilder->identifier(self::identifier())->build(),
         ];
     }
+
+    private static function identifier(): string
+    {
+        return 'ergebnis.noIsset';
+    }
 }
diff --git a/src/Files/DeclareStrictTypesRule.php b/src/Files/DeclareStrictTypesRule.php
index 399f287c..b91a1d2c 100644
--- a/src/Files/DeclareStrictTypesRule.php
+++ b/src/Files/DeclareStrictTypesRule.php
@@ -72,7 +72,12 @@ public function processNode(
         $ruleErrorBuilder = Rules\RuleErrorBuilder::message('File is missing a "declare(strict_types=1)" declaration.');
 
         return [
-            $ruleErrorBuilder->build(),
+            $ruleErrorBuilder->identifier(self::identifier())->build(),
         ];
     }
+
+    private static function identifier(): string
+    {
+        return 'ergebnis.declareStrictTypes';
+    }
 }
diff --git a/src/Functions/NoNullableReturnTypeDeclarationRule.php b/src/Functions/NoNullableReturnTypeDeclarationRule.php
index e143c51e..fb87955d 100644
--- a/src/Functions/NoNullableReturnTypeDeclarationRule.php
+++ b/src/Functions/NoNullableReturnTypeDeclarationRule.php
@@ -54,7 +54,7 @@ public function processNode(
         ));
 
         return [
-            $ruleErrorBuilder->build(),
+            $ruleErrorBuilder->identifier(self::identifier())->build(),
         ];
     }
 
@@ -80,4 +80,9 @@ private static function hasNullableReturnType(Node\Stmt\Function_ $node): bool
 
         return false;
     }
+
+    private static function identifier(): string
+    {
+        return 'ergebnis.functions.noNullableReturnTypeDeclaration';
+    }
 }
diff --git a/src/Functions/NoParameterWithNullDefaultValueRule.php b/src/Functions/NoParameterWithNullDefaultValueRule.php
index be7b41e4..7bb9690d 100644
--- a/src/Functions/NoParameterWithNullDefaultValueRule.php
+++ b/src/Functions/NoParameterWithNullDefaultValueRule.php
@@ -71,7 +71,12 @@ public function processNode(
                 $parameterName,
             ));
 
-            return $ruleErrorBuilder->build();
+            return $ruleErrorBuilder->identifier(self::identifier())->build();
         }, $params);
     }
+
+    private static function identifier(): string
+    {
+        return 'ergebnis.functions.noParameterWithNullDefaultValue';
+    }
 }
diff --git a/src/Functions/NoParameterWithNullableTypeDeclarationRule.php b/src/Functions/NoParameterWithNullableTypeDeclarationRule.php
index 5182a2f0..5e1020db 100644
--- a/src/Functions/NoParameterWithNullableTypeDeclarationRule.php
+++ b/src/Functions/NoParameterWithNullableTypeDeclarationRule.php
@@ -67,7 +67,7 @@ public function processNode(
                 $parameterName,
             ));
 
-            return $ruleErrorBuilder->build();
+            return $ruleErrorBuilder->identifier(self::identifier())->build();
         }, $params);
     }
 
@@ -93,4 +93,9 @@ private static function isNullable(Node\Param $node): bool
 
         return false;
     }
+
+    private static function identifier(): string
+    {
+        return 'ergebnis.functions.noParameterWithNullableTypeDeclaration';
+    }
 }
diff --git a/src/Methods/FinalInAbstractClassRule.php b/src/Methods/FinalInAbstractClassRule.php
index e67318e0..27b503ce 100644
--- a/src/Methods/FinalInAbstractClassRule.php
+++ b/src/Methods/FinalInAbstractClassRule.php
@@ -75,7 +75,12 @@ public function processNode(
         ));
 
         return [
-            $ruleErrorBuilder->build(),
+            $ruleErrorBuilder->identifier(self::identifier())->build(),
         ];
     }
+
+    private static function identifier(): string
+    {
+        return 'ergebnis.methods.finalInAbstractClass';
+    }
 }
diff --git a/src/Methods/NoConstructorParameterWithDefaultValueRule.php b/src/Methods/NoConstructorParameterWithDefaultValueRule.php
index 0853696e..5956e83c 100644
--- a/src/Methods/NoConstructorParameterWithDefaultValueRule.php
+++ b/src/Methods/NoConstructorParameterWithDefaultValueRule.php
@@ -73,7 +73,7 @@ public function processNode(
                     $parameterName,
                 ));
 
-                return $ruleErrorBuilder->build();
+                return $ruleErrorBuilder->identifier(self::identifier())->build();
             }, $params);
         }
 
@@ -93,4 +93,9 @@ public function processNode(
             );
         }, $params);
     }
+
+    private static function identifier(): string
+    {
+        return 'ergebnis.methods.noConstructorParameterWithDefaultValue';
+    }
 }
diff --git a/src/Methods/NoNullableReturnTypeDeclarationRule.php b/src/Methods/NoNullableReturnTypeDeclarationRule.php
index 8f580984..46efeb8e 100644
--- a/src/Methods/NoNullableReturnTypeDeclarationRule.php
+++ b/src/Methods/NoNullableReturnTypeDeclarationRule.php
@@ -55,7 +55,7 @@ public function processNode(
             ));
 
             return [
-                $ruleErrorBuilder->build(),
+                $ruleErrorBuilder->identifier(self::identifier())->build(),
             ];
         }
 
@@ -66,7 +66,7 @@ public function processNode(
         ));
 
         return [
-            $ruleErrorBuilder->build(),
+            $ruleErrorBuilder->identifier(self::identifier())->build(),
         ];
     }
 
@@ -92,4 +92,9 @@ private static function hasNullableReturnType(Node\Stmt\ClassMethod $node): bool
 
         return false;
     }
+
+    private static function identifier(): string
+    {
+        return 'ergebnis.methods.noNullableReturnTypeDeclaration';
+    }
 }
diff --git a/src/Methods/NoParameterWithContainerTypeDeclarationRule.php b/src/Methods/NoParameterWithContainerTypeDeclarationRule.php
index 5ed0ae8c..03d8ddd6 100644
--- a/src/Methods/NoParameterWithContainerTypeDeclarationRule.php
+++ b/src/Methods/NoParameterWithContainerTypeDeclarationRule.php
@@ -167,7 +167,7 @@ private static function createError(
                 $classUsedInTypeDeclaration->getName(),
             ));
 
-            return $ruleErrorBuilder->build();
+            return $ruleErrorBuilder->identifier(self::identifier())->build();
         }
 
         $ruleErrorBuilder = Rules\RuleErrorBuilder::message(\sprintf(
@@ -178,6 +178,11 @@ private static function createError(
             $classUsedInTypeDeclaration->getName(),
         ));
 
-        return $ruleErrorBuilder->build();
+        return $ruleErrorBuilder->identifier(self::identifier())->build();
+    }
+
+    private static function identifier(): string
+    {
+        return 'ergebnis.methods.noParameterWithContainerTypeDeclaration';
     }
 }
diff --git a/src/Methods/NoParameterWithNullDefaultValueRule.php b/src/Methods/NoParameterWithNullDefaultValueRule.php
index cd4f54f8..57d3e9ee 100644
--- a/src/Methods/NoParameterWithNullDefaultValueRule.php
+++ b/src/Methods/NoParameterWithNullDefaultValueRule.php
@@ -76,13 +76,13 @@ public function processNode(
                     $parameterName,
                 ));
 
-                return $ruleErrorBuilder->build();
+                return $ruleErrorBuilder->identifier(self::identifier())->build();
             }, $params);
         }
 
         $className = $classReflection->getName();
 
-        return \array_map(static function (Node\Param $node) use ($className, $methodName): Rules\RuleError {
+        return \array_values(\array_map(static function (Node\Param $node) use ($className, $methodName): Rules\RuleError {
             /** @var Node\Expr\Variable $variable */
             $variable = $node->var;
 
@@ -96,7 +96,12 @@ public function processNode(
                 $parameterName,
             ));
 
-            return $ruleErrorBuilder->build();
-        }, $params);
+            return $ruleErrorBuilder->identifier(self::identifier())->build();
+        }, $params));
+    }
+
+    private static function identifier(): string
+    {
+        return 'ergebnis.methods.noParameterWithNullDefaultValue';
     }
 }
diff --git a/src/Methods/NoParameterWithNullableTypeDeclarationRule.php b/src/Methods/NoParameterWithNullableTypeDeclarationRule.php
index ba5283dc..ecd0faa3 100644
--- a/src/Methods/NoParameterWithNullableTypeDeclarationRule.php
+++ b/src/Methods/NoParameterWithNullableTypeDeclarationRule.php
@@ -59,7 +59,7 @@ public function processNode(
         $classReflection = $scope->getClassReflection();
 
         if ($classReflection->isAnonymous()) {
-            return \array_map(static function (Node\Param $node) use ($methodName): Rules\RuleError {
+            return \array_values(\array_map(static function (Node\Param $node) use ($methodName): Rules\RuleError {
                 /** @var Node\Expr\Variable $variable */
                 $variable = $node->var;
 
@@ -72,13 +72,13 @@ public function processNode(
                     $parameterName,
                 ));
 
-                return $ruleErrorBuilder->build();
-            }, $params);
+                return $ruleErrorBuilder->identifier(self::identifier())->build();
+            }, $params));
         }
 
         $className = $classReflection->getName();
 
-        return \array_map(static function (Node\Param $node) use ($className, $methodName): Rules\RuleError {
+        return \array_values(\array_map(static function (Node\Param $node) use ($className, $methodName): Rules\RuleError {
             /** @var Node\Expr\Variable $variable */
             $variable = $node->var;
 
@@ -92,8 +92,8 @@ public function processNode(
                 $parameterName,
             ));
 
-            return $ruleErrorBuilder->build();
-        }, $params);
+            return $ruleErrorBuilder->identifier(self::identifier())->build();
+        }, $params));
     }
 
     private static function isNullable(Node\Param $node): bool
@@ -118,4 +118,9 @@ private static function isNullable(Node\Param $node): bool
 
         return false;
     }
+
+    private static function identifier(): string
+    {
+        return 'ergebnis.methods.noParameterWithContainerTypeDeclaration';
+    }
 }
diff --git a/src/Methods/PrivateInFinalClassRule.php b/src/Methods/PrivateInFinalClassRule.php
index aad66be0..08c53140 100644
--- a/src/Methods/PrivateInFinalClassRule.php
+++ b/src/Methods/PrivateInFinalClassRule.php
@@ -75,7 +75,12 @@ public function processNode(
         ));
 
         return [
-            $ruleErrorBuilder->build(),
+            $ruleErrorBuilder->identifier(self::identifier())->build(),
         ];
     }
+
+    private static function identifier(): string
+    {
+        return 'ergebnis.methods.privateInFinalClass';
+    }
 }
diff --git a/src/Statements/NoSwitchRule.php b/src/Statements/NoSwitchRule.php
index 1845a224..9968f13a 100644
--- a/src/Statements/NoSwitchRule.php
+++ b/src/Statements/NoSwitchRule.php
@@ -34,7 +34,12 @@ public function processNode(
         $ruleErrorBuilder = Rules\RuleErrorBuilder::message('Control structures using switch should not be used.');
 
         return [
-            $ruleErrorBuilder->build(),
+            $ruleErrorBuilder->identifier(self::identifier())->build(),
         ];
     }
+
+    private static function identifier(): string
+    {
+        return 'ergebnis.statements.noSwitch';
+    }
 }