diff --git a/package_manager/src/ComposerInspector.php b/package_manager/src/ComposerInspector.php
index 1270c7ce59e60ff285564b36996f8ccba3c4f78b..b8e165321f9adeefc785fff907345059521363a1 100644
--- a/package_manager/src/ComposerInspector.php
+++ b/package_manager/src/ComposerInspector.php
@@ -263,7 +263,7 @@ class ComposerInspector implements LoggerAwareInterface {
       }
     }
     $output = $this->processCallback->getOutput();
-    return isset($output) ? trim($output) : $output;
+    return $output ? trim(implode('', $output)) : NULL;
   }
 
   /**
diff --git a/package_manager/src/ProcessOutputCallback.php b/package_manager/src/ProcessOutputCallback.php
index 0f4096ebdfa0b9494d04a27efa8d6f6835f23da7..86eaabde2f98e731f27d869cc35e98ccd710845d 100644
--- a/package_manager/src/ProcessOutputCallback.php
+++ b/package_manager/src/ProcessOutputCallback.php
@@ -29,14 +29,14 @@ final class ProcessOutputCallback implements OutputCallbackInterface, LoggerAwar
    *
    * @var string
    */
-  private string $outBuffer = '';
+  private array $outBuffer = [];
 
   /**
    * The error buffer.
    *
    * @var string
    */
-  private string $errorBuffer = '';
+  private array $errorBuffer = [];
 
   /**
    * Constructs a ProcessOutputCallback object.
@@ -51,10 +51,10 @@ final class ProcessOutputCallback implements OutputCallbackInterface, LoggerAwar
   public function __invoke(OutputTypeEnum $type, string $buffer): void {
 
     if ($type === OutputTypeEnum::OUT) {
-      $this->outBuffer .= $buffer;
+      $this->outBuffer[] = $buffer;
     }
     elseif ($type === OutputTypeEnum::ERR) {
-      $this->errorBuffer .= $buffer;
+      $this->errorBuffer[] = $buffer;
     }
   }
 
@@ -66,12 +66,12 @@ final class ProcessOutputCallback implements OutputCallbackInterface, LoggerAwar
    * @return string|null
    *   The output or NULL if there is none.
    */
-  public function getOutput(): ?string {
+  public function getOutput(): array {
     $error_output = $this->getErrorOutput();
     if ($error_output) {
-      $this->logger->warning($error_output);
+      $this->logger->warning(implode('', $error_output));
     }
-    return trim($this->outBuffer) !== '' ? $this->outBuffer : NULL;
+    return $this->outBuffer;
   }
 
   /**
@@ -82,8 +82,8 @@ final class ProcessOutputCallback implements OutputCallbackInterface, LoggerAwar
    */
   public function parseJsonOutput(): mixed {
     $output = $this->getOutput();
-    if ($output !== NULL) {
-      return json_decode($output, TRUE, flags: JSON_THROW_ON_ERROR);
+    if ($output) {
+      return json_decode(trim(implode('', $output)), TRUE, flags: JSON_THROW_ON_ERROR);
     }
     return NULL;
   }
@@ -94,8 +94,22 @@ final class ProcessOutputCallback implements OutputCallbackInterface, LoggerAwar
    * @return string|null
    *   The error output or NULL if there isn't any.
    */
-  public function getErrorOutput(): ?string {
-    return trim($this->errorBuffer) !== '' ? $this->errorBuffer : NULL;
+  public function getErrorOutput(): array {
+    return $this->errorBuffer;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function clearErrorOutput(): void {
+    $this->errorBuffer = [];
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function clearOutput(): void {
+    $this->outBuffer = [];
   }
 
   /**
@@ -104,8 +118,8 @@ final class ProcessOutputCallback implements OutputCallbackInterface, LoggerAwar
    * @return self
    */
   public function reset(): self {
-    $this->errorBuffer = '';
-    $this->outBuffer = '';
+    $this->clearErrorOutput();
+    $this->clearOutput();
     return $this;
   }
 
diff --git a/package_manager/tests/modules/fixture_manipulator/src/FixtureManipulator.php b/package_manager/tests/modules/fixture_manipulator/src/FixtureManipulator.php
index 6de6b6d443baf48ae83064c09184792f3de4396d..43b75169dcb3bf94789e0313858170246a1139ed 100644
--- a/package_manager/tests/modules/fixture_manipulator/src/FixtureManipulator.php
+++ b/package_manager/tests/modules/fixture_manipulator/src/FixtureManipulator.php
@@ -445,6 +445,34 @@ class FixtureManipulator {
         }
       }
 
+      /**
+       * {@inheritdoc}
+       */
+      public function clearErrorOutput(): void {
+        throw new \LogicException("Unexpected call to clearErrorOutput().");
+      }
+
+      /**
+       * {@inheritdoc}
+       */
+      public function clearOutput(): void {
+        throw new \LogicException("Unexpected call to clearOutput().");
+      }
+
+      /**
+       * {@inheritdoc}
+       */
+      public function getErrorOutput(): array {
+        throw new \LogicException("Unexpected call to getErrorOutput().");
+      }
+
+      /**
+       * {@inheritdoc}
+       */
+      public function getOutput(): array {
+        throw new \LogicException("Unexpected call to getOutput().");
+      }
+
     };
     /** @var \PhpTuf\ComposerStager\API\Process\Service\ComposerProcessRunnerInterface $runner */
     $runner = \Drupal::service(ComposerProcessRunnerInterface::class);
diff --git a/package_manager/tests/src/Build/TemplateProjectTestBase.php b/package_manager/tests/src/Build/TemplateProjectTestBase.php
index 8fbca7bc3c1606d4a7063dc2e6dc1db9aaba5fa2..d815f7ca70b49345ee94f44528bfb2e6becc12cf 100644
--- a/package_manager/tests/src/Build/TemplateProjectTestBase.php
+++ b/package_manager/tests/src/Build/TemplateProjectTestBase.php
@@ -63,6 +63,18 @@ abstract class TemplateProjectTestBase extends QuickStartTestBase {
    */
   protected const MAX_EXECUTION_TIME = 20;
 
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp(): void {
+    // Build tests cannot be run if Sqlite minimum version is not met.
+    $sqlite = (new \PDO('sqlite::memory:'))->query('select sqlite_version()')->fetch()[0];
+    if (version_compare($sqlite, Tasks::SQLITE_MINIMUM_VERSION) < 0) {
+      $this->markTestSkipped();
+    }
+    parent::setUp();
+  }
+
   /**
    * {@inheritdoc}
    */
diff --git a/package_manager/tests/src/Kernel/ComposerInspectorTest.php b/package_manager/tests/src/Kernel/ComposerInspectorTest.php
index 297498dd48820ac6801b539a97c3c74e1d2594dc..466112f4a99e41e4d4e70cf6ae57ba888b22fdea 100644
--- a/package_manager/tests/src/Kernel/ComposerInspectorTest.php
+++ b/package_manager/tests/src/Kernel/ComposerInspectorTest.php
@@ -10,7 +10,6 @@ use Drupal\fixture_manipulator\ActiveFixtureManipulator;
 use Drupal\package_manager\ComposerInspector;
 use Drupal\package_manager\Exception\ComposerNotReadyException;
 use Drupal\package_manager\InstalledPackage;
-use Drupal\package_manager\ProcessOutputCallback;
 use Drupal\package_manager\InstalledPackagesList;
 use Drupal\Tests\package_manager\Traits\InstalledPackagesListTrait;
 use Drupal\package_manager\PathLocator;
@@ -19,6 +18,7 @@ use PhpTuf\ComposerStager\API\Exception\RuntimeException;
 use PhpTuf\ComposerStager\API\Path\Factory\PathFactoryInterface;
 use PhpTuf\ComposerStager\API\Precondition\Service\ComposerIsAvailableInterface;
 use PhpTuf\ComposerStager\API\Process\Service\ComposerProcessRunnerInterface;
+use PhpTuf\ComposerStager\API\Process\Service\OutputCallbackInterface;
 use PhpTuf\ComposerStager\API\Process\Value\OutputTypeEnum;
 use Prophecy\Argument;
 use Prophecy\Prophecy\ObjectProphecy;
@@ -250,10 +250,18 @@ class ComposerInspectorTest extends PackageManagerKernelTestBase {
   public function testVersionCheck(?string $reported_version, ?string $expected_message): void {
     $runner = $this->mockComposerRunner($reported_version);
 
+    // Mock the ComposerIsAvailableInterface so that if it uses the Composer
+    // runner it will not affect the test expectations.
+    $composerPrecondition = $this->prophesize(ComposerIsAvailableInterface::class);
+    $composerPrecondition
+      ->assertIsFulfilled(Argument::cetera())
+      ->shouldBeCalledOnce();
+    $this->container->set(ComposerIsAvailableInterface::class, $composerPrecondition->reveal());
+
     // The result of the version check is statically cached, so the runner
     // should only be called once, even though we call validate() twice in this
     // test.
-    $runner->getMethodProphecies('run')[0]->shouldBeCalledOnce();
+    $runner->getMethodProphecies('run')[0]->withArguments([['--format=json'], NULL, [], Argument::any()])->shouldBeCalledOnce();
     // The runner should be called with `validate` as the first argument, but
     // it won't affect the outcome of this test.
     $runner->run(Argument::withEntry(0, 'validate'));
@@ -535,7 +543,7 @@ class ComposerInspectorTest extends PackageManagerKernelTestBase {
       ]);
 
       $callback = end($arguments_passed_to_runner);
-      assert($callback instanceof ProcessOutputCallback);
+      assert($callback instanceof OutputCallbackInterface);
       $callback(OutputTypeEnum::OUT, $command_output);
     };
 
diff --git a/package_manager/tests/src/Unit/ProcessOutputCallbackTest.php b/package_manager/tests/src/Unit/ProcessOutputCallbackTest.php
index 84b9ed63e81449c1e7b007e6c8d42bd002d163d4..b401fbd119cb8e477f578a3ad8d4ccfd09e820a9 100644
--- a/package_manager/tests/src/Unit/ProcessOutputCallbackTest.php
+++ b/package_manager/tests/src/Unit/ProcessOutputCallbackTest.php
@@ -38,13 +38,13 @@ class ProcessOutputCallbackTest extends UnitTestCase {
     $error_text = 'What happened?';
     $callback(OutputTypeEnum::ERR, $error_text);
 
-    $this->assertSame($error_text, $callback->getErrorOutput());
+    $this->assertSame([$error_text], $callback->getErrorOutput());
     // The error should not yet be logged.
     $this->assertEmpty($logger->records);
 
     // There should be no output data, but calling getOutput() should log the
     // error.
-    $this->assertNull($callback->getOutput());
+    $this->assertSame([], $callback->getOutput());
     $this->assertNull($callback->parseJsonOutput());
     $this->assertTrue($logger->hasWarning($error_text));
 
@@ -63,8 +63,8 @@ class ProcessOutputCallbackTest extends UnitTestCase {
     $callback->setLogger($logger);
 
     // The buffers should initially be empty, and nothing should be logged.
-    $this->assertNull($callback->getOutput());
-    $this->assertNull($callback->getErrorOutput());
+    $this->assertSame([], $callback->getOutput());
+    $this->assertSame([], $callback->getErrorOutput());
     $this->assertNull($callback->parseJsonOutput());
     $this->assertEmpty($logger->records);
 
@@ -77,13 +77,15 @@ class ProcessOutputCallbackTest extends UnitTestCase {
     $json = json_encode($data, JSON_PRETTY_PRINT);
     // Ensure the JSON is a multi-line string.
     $this->assertGreaterThan(1, substr_count($json, "\n"));
+    $expected_output = [];
     foreach (explode("\n", $json) as $line) {
       $callback(OutputTypeEnum::OUT, "$line\n");
+      $expected_output[] = "$line\n";
     }
-    $this->assertSame("$json\n", $callback->getOutput());
+    $this->assertSame($expected_output, $callback->getOutput());
     // Ensure that parseJsonOutput() can parse the data without errors.
     $this->assertSame($data, $callback->parseJsonOutput());
-    $this->assertNull($callback->getErrorOutput());
+    $this->assertSame([], $callback->getErrorOutput());
     $this->assertEmpty($logger->records);
 
     // If we send error output, it should be logged, but we should still be able
@@ -91,34 +93,37 @@ class ProcessOutputCallbackTest extends UnitTestCase {
     $callback(OutputTypeEnum::ERR, 'Oh no, what happened?');
     $callback(OutputTypeEnum::ERR, 'Really what happened?!');
     $this->assertSame($data, $callback->parseJsonOutput());
-    $this->assertSame('Oh no, what happened?Really what happened?!', $callback->getErrorOutput());
+    $expected_error = ['Oh no, what happened?', 'Really what happened?!'];
+    $this->assertSame($expected_error, $callback->getErrorOutput());
     $this->assertTrue($logger->hasWarning('Oh no, what happened?Really what happened?!'));
 
     // Send more output and error data to the callback; they should be appended
     // to the data we previously sent.
     $callback(OutputTypeEnum::OUT, '{}');
+    $expected_output[] = '{}';
     $callback(OutputTypeEnum::ERR, 'new Error 1!');
     $callback(OutputTypeEnum::ERR, 'new Error 2!');
+    $expected_error[] = 'new Error 1!';
+    $expected_error[] = 'new Error 2!';
     // The output buffer will no longer be valid JSON, so don't try to parse it.
-    $this->assertSame("$json\n{}", $callback->getOutput());
-    $expected_error = 'Oh no, what happened?Really what happened?!new Error 1!new Error 2!';
+    $this->assertSame($expected_output, $callback->getOutput());
     $this->assertSame($expected_error, $callback->getErrorOutput());
-    $this->assertTrue($logger->hasWarning($expected_error));
+    $this->assertTrue($logger->hasWarning(implode('', $expected_error)));
     // The previously logged error output should still be there.
     $this->assertTrue($logger->hasWarning('Oh no, what happened?Really what happened?!'));
 
     // Clear all stored output and errors.
     $callback->reset();
-    $this->assertNull($callback->getOutput());
-    $this->assertNull($callback->getErrorOutput());
+    $this->assertSame([], $callback->getOutput());
+    $this->assertSame([], $callback->getErrorOutput());
     $this->assertNull($callback->parseJsonOutput());
 
     // Send more output and error data.
     $callback(OutputTypeEnum::OUT, 'Bonjour!');
     $callback(OutputTypeEnum::ERR, 'You continue to annoy me.');
     // We should now only see the stuff we just sent...
-    $this->assertSame('Bonjour!', $callback->getOutput());
-    $this->assertSame('You continue to annoy me.', $callback->getErrorOutput());
+    $this->assertSame(['Bonjour!'], $callback->getOutput());
+    $this->assertSame(['You continue to annoy me.'], $callback->getErrorOutput());
     $this->assertTrue($logger->hasWarning('You continue to annoy me.'));
     // ...but the previously logged errors should still be there.
     $this->assertTrue($logger->hasWarning('Oh no, what happened?Really what happened?!new Error 1!new Error 2!'));