diff --git a/src/Plugin/DataType/ComponentInputs.php b/src/Plugin/DataType/ComponentInputs.php
index 87333e027b22123db433457df5b61ad622577eb2..704600a1cba275230b08af8bc335182964205922 100644
--- a/src/Plugin/DataType/ComponentInputs.php
+++ b/src/Plugin/DataType/ComponentInputs.php
@@ -8,7 +8,9 @@ use Drupal\Component\Serialization\Json;
 use Drupal\Core\StringTranslation\TranslatableMarkup;
 use Drupal\Core\TypedData\Attribute\DataType;
 use Drupal\Core\TypedData\TypedData;
+use Drupal\experience_builder\ComponentSource\ComponentSourceInterface;
 use Drupal\experience_builder\MissingComponentInputsException;
+use Drupal\experience_builder\Plugin\Field\FieldType\ComponentTreeItem;
 
 /**
  * @todo Implement ListInterface because it conceptually fits, but … what does it get us?
@@ -125,8 +127,17 @@ class ComponentInputs extends TypedData implements \Stringable {
    * @throws \Drupal\experience_builder\MissingComponentInputsException
    */
   public function getValues(string $component_instance_uuid): array {
+    $item = $this->parent;
+    assert($item instanceof ComponentTreeItem);
+    $tree = $item->get('tree');
+    assert($tree instanceof ComponentTreeStructure);
+    $source = $tree->getComponentSource($component_instance_uuid);
+    \assert($source instanceof ComponentSourceInterface);
     if (!array_key_exists($component_instance_uuid, $this->inputs)) {
-      throw new MissingComponentInputsException($component_instance_uuid);
+      if ($source->requiresExplicitInput()) {
+        throw new MissingComponentInputsException($component_instance_uuid);
+      }
+      return [];
     }
 
     return $this->inputs[$component_instance_uuid];
diff --git a/src/Plugin/Field/FieldType/ComponentTreeItem.php b/src/Plugin/Field/FieldType/ComponentTreeItem.php
index 1dcceffbe1e7a3a455ff5a99895048aeddd088cb..72e5856fd75144bab54d32a8c334801ef1bcfcb8 100644
--- a/src/Plugin/Field/FieldType/ComponentTreeItem.php
+++ b/src/Plugin/Field/FieldType/ComponentTreeItem.php
@@ -16,6 +16,7 @@ use Drupal\Core\Render\RenderableInterface;
 use Drupal\Core\StringTranslation\TranslatableMarkup;
 use Drupal\Core\TypedData\DataDefinition;
 use Drupal\experience_builder\Entity\Component;
+use Drupal\experience_builder\Plugin\DataType\ComponentInputs;
 use Drupal\experience_builder\Plugin\DataType\ComponentTreeStructure;
 use Drupal\experience_builder\ShapeMatcher\FieldForComponentSuggester;
 use Symfony\Component\Validator\ConstraintViolation;
@@ -261,6 +262,7 @@ class ComponentTreeItem extends FieldItemBase implements RenderableInterface {
   public function preSave(): void {
     $tree = $this->get('tree');
     $inputs = $this->get('inputs');
+    assert($inputs instanceof ComponentInputs);
 
     $component_instance_uuids = $tree->getComponentInstanceUuids();
     $entity = $this->getRoot() === $this ? NULL : $this->getEntity();
@@ -305,7 +307,8 @@ class ComponentTreeItem extends FieldItemBase implements RenderableInterface {
     // This *internal-only* validation does not need to happen using validation
     // constraints because it does not validate user input: it only helps ensure
     // that the logic of this field type is correct.
-    if (array_intersect($component_instance_uuids, $inputs->getComponentInstanceUuids()) !== $component_instance_uuids) {
+    $input_required_uuids = array_filter($tree->getComponentInstanceUuids(), static fn(string $uuid) => $tree->getComponentSource($uuid)?->requiresExplicitInput() === TRUE);
+    if (array_intersect($input_required_uuids, $inputs->getComponentInstanceUuids()) !== $input_required_uuids) {
       throw new \LogicException(sprintf('The component UUIDs in the tree and inputs values do not match! Put a breakpoint here and figure out why.'));
     }
 
diff --git a/tests/src/Unit/DataType/ComponentInputsTest.php b/tests/src/Unit/DataType/ComponentInputsTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..0e841d92967ca08b84a65d070004d55522a6f416
--- /dev/null
+++ b/tests/src/Unit/DataType/ComponentInputsTest.php
@@ -0,0 +1,79 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Drupal\Tests\experience_builder\Unit\Plugin\DataType;
+
+use Drupal\Component\Serialization\Json;
+use Drupal\Core\TypedData\DataDefinitionInterface;
+use Drupal\experience_builder\ComponentSource\ComponentSourceInterface;
+use Drupal\experience_builder\MissingComponentInputsException;
+use Drupal\experience_builder\Plugin\DataType\ComponentInputs;
+use Drupal\experience_builder\Plugin\DataType\ComponentTreeStructure;
+use Drupal\experience_builder\Plugin\Field\FieldType\ComponentTreeItem;
+use Drupal\Tests\UnitTestCase;
+
+/**
+ * @coversDefaultClass \Drupal\experience_builder\Plugin\DataType\ComponentInputs
+ */
+class ComponentInputsTest extends UnitTestCase {
+
+  /**
+   * @covers ::getValues
+   */
+  public function testGetValues(): void {
+    $existing_component_uuid = 'test-component-uuid';
+
+    // Create test data.
+    $test_inputs = [
+      $existing_component_uuid => [
+        'title' => [
+          'sourceType' => 'static:text',
+          'value' => 'Test Title',
+          'expression' => '',
+        ],
+        'body' => [
+          'sourceType' => 'static:text',
+          'value' => 'Test Body',
+          'expression' => '',
+        ],
+      ],
+    ];
+    $component_source = $this->prophesize(ComponentSourceInterface::class);
+
+    $tree = $this->prophesize(ComponentTreeStructure::class);
+    $tree->getComponentId($existing_component_uuid)->willReturn('test-component-id');
+    $tree->getComponentSource($existing_component_uuid)->willReturn($component_source->reveal());
+
+    $item = $this->prophesize(ComponentTreeItem::class);
+    $item->get('tree')->willReturn($tree->reveal());
+    $item->onChange(NULL)->shouldBeCalledTimes(1);
+
+    $component_inputs = new ComponentInputs(
+      $this->prophesize(DataDefinitionInterface::class)->reveal(),
+      NULL,
+      $item->reveal()
+    );
+    $component_inputs->setValue(Json::encode($test_inputs));
+
+    // Test getting values for a existing UUID.
+    $this->assertEquals(
+      $test_inputs[$existing_component_uuid],
+      $component_inputs->getValues($existing_component_uuid)
+    );
+
+    // Test getting values for a non-existing UUID that doesn't require explicit input.
+    $non_existing_uuid = 'non-existing-uuid';
+    $tree->getComponentSource($non_existing_uuid)->willReturn($component_source->reveal());
+    $component_source->requiresExplicitInput()->willReturn(FALSE);
+
+    $values = $component_inputs->getValues($non_existing_uuid);
+    $this->assertEquals([], $values);
+
+    // Test getting values for a non-existing UUID that requires explicit input.
+    $component_source->requiresExplicitInput()->willReturn(TRUE);
+    $this->expectException(MissingComponentInputsException::class);
+    $component_inputs->getValues($non_existing_uuid);
+  }
+
+}