diff --git a/core/lib/Drupal/Core/Theme/Component/ComponentValidator.php b/core/lib/Drupal/Core/Theme/Component/ComponentValidator.php
index 530e7fc5a6df76c65ac94896624d2496491d8bd7..357c3ab21c314e6a68e305946d8c9e3cd7f5a80b 100644
--- a/core/lib/Drupal/Core/Theme/Component/ComponentValidator.php
+++ b/core/lib/Drupal/Core/Theme/Component/ComponentValidator.php
@@ -81,6 +81,28 @@ public function validateDefinition(array $definition, bool $enforce_schemas): bo
     if (($schema['properties'] ?? NULL) === []) {
       $schema['properties'] = new \stdClass();
     }
+
+    // Ensure that all property types are strings. For example, a null value
+    // will not automatically convert to 'null', which will lead to a PHP error
+    // that is hard to trace back to the property.
+    $non_string_props = [];
+    \array_walk($prop_names, function (string $prop) use (&$non_string_props, $schema) {
+      $type = $schema['properties'][$prop]['type'];
+      $types = !\is_array($type) ? [$type] : $type;
+      $non_string_types = \array_filter($types, static fn (mixed $type) => !\is_string($type));
+      if ($non_string_types) {
+        $non_string_props[] = $prop;
+      }
+    });
+
+    if ($non_string_props) {
+      throw new InvalidComponentException(\sprintf(
+        'The component "%s" uses non-string types for properties: %s.',
+        $definition['id'],
+        \implode(', ', $non_string_props),
+      ));
+    }
+
     $classes_per_prop = $this->getClassProps($schema);
     $missing_class_errors = [];
     foreach ($classes_per_prop as $prop_name => $class_types) {
diff --git a/core/tests/Drupal/Tests/Core/Theme/Component/ComponentValidatorTest.php b/core/tests/Drupal/Tests/Core/Theme/Component/ComponentValidatorTest.php
index 7c76a1830558981e7fb37b261ab313a93ff46396..d24d2df7989ccf8fd430dcaf1e8d2e1780e49ee8 100644
--- a/core/tests/Drupal/Tests/Core/Theme/Component/ComponentValidatorTest.php
+++ b/core/tests/Drupal/Tests/Core/Theme/Component/ComponentValidatorTest.php
@@ -65,24 +65,43 @@ public function testValidateDefinitionInvalid(array $definition): void {
   /**
    * Data provider with invalid component definitions.
    *
-   * @return array
-   *   The data.
+   * @return \Generator
+   *   Returns the generator with the invalid definitions.
    */
-  public static function dataProviderValidateDefinitionInvalid(): array {
+  public static function dataProviderValidateDefinitionInvalid(): \Generator {
     $valid_cta = static::loadComponentDefinitionFromFs('my-cta');
+
     $cta_with_missing_required = $valid_cta;
     unset($cta_with_missing_required['path']);
+    yield 'missing required' => [$cta_with_missing_required];
+
     $cta_with_invalid_class = $valid_cta;
     $cta_with_invalid_class['props']['properties']['attributes']['type'] = 'Drupal\Foo\Invalid';
+    yield 'invalid class' => [$cta_with_invalid_class];
+
     $cta_with_invalid_enum = array_merge(
       $valid_cta,
       ['extension_type' => 'invalid'],
     );
-    return [
-      [$cta_with_missing_required],
-      [$cta_with_invalid_class],
-      [$cta_with_invalid_enum],
-    ];
+    yield 'invalid enum' => [$cta_with_invalid_enum];
+
+    // A list of property types that are not strings, but can be provided via
+    // YAML.
+    $non_string_types = [NULL, 123, 123.45, TRUE];
+    foreach ($non_string_types as $non_string_type) {
+      $cta_with_non_string_prop_type = $valid_cta;
+      $cta_with_non_string_prop_type['props']['properties']['text']['type'] = $non_string_type;
+      yield "non string type ($non_string_type)" => [$cta_with_non_string_prop_type];
+
+      // Same, but as a part of the list of allowed types.
+      $cta_with_non_string_prop_type['props']['properties']['text']['type'] = ['string', $non_string_type];
+      yield "non string type ($non_string_type) in a list of types" => [$cta_with_non_string_prop_type];
+    }
+
+    // The array is a valid value for the 'type' parameter, but it is not
+    // allowed as the allowed type.
+    $cta_with_non_string_prop_type['props']['properties']['text']['type'] = ['string', []];
+    yield 'non string type (Array)' => [$cta_with_non_string_prop_type];
   }
 
   /**