diff --git a/core/modules/migrate_drupal_ui/src/Form/CredentialForm.php b/core/modules/migrate_drupal_ui/src/Form/CredentialForm.php
index cd767cc3d1..c2374d2ecc 100644
--- a/core/modules/migrate_drupal_ui/src/Form/CredentialForm.php
+++ b/core/modules/migrate_drupal_ui/src/Form/CredentialForm.php
@@ -2,9 +2,12 @@
 
 namespace Drupal\migrate_drupal_ui\Form;
 
+use Drupal\Component\Utility;
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\Render\RendererInterface;
 use Drupal\Core\TempStore\PrivateTempStoreFactory;
+use GuzzleHttp\ClientInterface;
+use GuzzleHttp\Exception\TransferException;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
@@ -22,16 +25,33 @@ class CredentialForm extends MigrateUpgradeFormBase {
   protected $renderer;
 
   /**
+   * The HTTP client to fetch the feed data with.
+   *
+   * @var \GuzzleHttp\ClientInterface
+   */
+  protected $httpClient;
+
+  /**
+   * An array of error information.
+   *
+   * @var array
+   */
+  protected $errors = [];
+
+  /**
    * CredentialForm constructor.
    *
    * @param \Drupal\Core\Render\RendererInterface $renderer
    *   The renderer service.
    * @param \Drupal\Core\TempStore\PrivateTempStoreFactory $tempstore_private
    *   The private tempstore factory.
+   * @param \GuzzleHttp\ClientInterface $http_client
+   *   A Guzzle client object.
    */
-  public function __construct(RendererInterface $renderer, PrivateTempStoreFactory $tempstore_private) {
+  public function __construct(RendererInterface $renderer, PrivateTempStoreFactory $tempstore_private, ClientInterface $http_client) {
     parent::__construct($tempstore_private);
     $this->renderer = $renderer;
+    $this->httpClient = $http_client;
   }
 
   /**
@@ -40,7 +60,8 @@ public function __construct(RendererInterface $renderer, PrivateTempStoreFactory
   public static function create(ContainerInterface $container) {
     return new static(
       $container->get('renderer'),
-      $container->get('tempstore.private')
+      $container->get('tempstore.private'),
+      $container->get('http_client')
     );
   }
 
@@ -75,6 +96,11 @@ public function buildForm(array $form, FormStateInterface $form_state) {
 
     $default_options = [];
 
+    $form['help'] = [
+      '#type' => 'item',
+      '#description' => $this->t('Provide the information to access the Drupal site you want to upgrade. Files can be imported into the upgraded site as well.  See the <a href=":url">Upgrade documentation for more detailed instructions</a>.', [':url' => 'https://www.drupal.org/upgrade/migrate']),
+    ];
+
     $form['version'] = [
       '#type' => 'radios',
       '#default_value' => 7,
@@ -145,6 +171,9 @@ public function buildForm(array $form, FormStateInterface $form_state) {
           ':input[name="version"]' => ['value' => '6'],
         ],
       ],
+      '#element_validate' => [
+        [$this, 'validatePaths'],
+      ],
     ];
 
     $form['source']['source_base_path'] = [
@@ -156,6 +185,9 @@ public function buildForm(array $form, FormStateInterface $form_state) {
           ':input[name="version"]' => ['value' => '7'],
         ],
       ],
+      '#element_validate' => [
+        [$this, 'validatePaths'],
+      ],
     ];
 
     $form['source']['source_private_file_path'] = [
@@ -168,6 +200,9 @@ public function buildForm(array $form, FormStateInterface $form_state) {
           ':input[name="version"]' => ['value' => '7'],
         ],
       ],
+      '#element_validate' => [
+        [$this, 'validatePaths'],
+      ],
     ];
 
     return $form;
@@ -177,7 +212,6 @@ public function buildForm(array $form, FormStateInterface $form_state) {
    * {@inheritdoc}
    */
   public function validateForm(array &$form, FormStateInterface $form_state) {
-
     // Retrieve the database driver from the form, use reflection to get the
     // namespace, and then construct a valid database array the same as in
     // settings.php.
@@ -191,25 +225,22 @@ public function validateForm(array &$form, FormStateInterface $form_state) {
     $database['namespace'] = substr($install_namespace, 0, strrpos($install_namespace, '\\'));
     $database['driver'] = $driver;
 
-    // Validate the driver settings and just end here if we have any issues.
-    if ($errors = $drivers[$driver]->validateDatabaseSettings($database)) {
-      foreach ($errors as $name => $message) {
-        $form_state->setErrorByName($name, $message);
-      }
-      return;
+    foreach ($drivers[$driver]->validateDatabaseSettings($database) as $key => $value) {
+      $this->errors[$key] = $value;
     }
 
     try {
       $connection = $this->getConnection($database);
       $version = (string) $this->getLegacyDrupalVersion($connection);
       if (!$version) {
-        $form_state->setErrorByName($database['driver'] . '][0', $this->t('Source database does not contain a recognizable Drupal version.'));
+        $this->errors[$database['driver'] . '][database'] = $this->t('Source database does not contain a recognizable Drupal version.');
       }
       elseif ($version !== (string) $form_state->getValue('version')) {
-        $form_state->setErrorByName($database['driver'] . '][0', $this->t('Source database is Drupal version @version but version @selected was selected.', [
-          '@version' => $version,
-          '@selected' => $form_state->getValue('version'),
-        ]));
+        $this->errors['version'] = $this->t('Source database is Drupal version @version but version @selected was selected.',
+          [
+            '@version' => $version,
+            '@selected' => $form_state->getValue('version'),
+          ]);
       }
       else {
         // Setup migrations and save form data to private store.
@@ -217,16 +248,64 @@ public function validateForm(array &$form, FormStateInterface $form_state) {
       }
     }
     catch (\Exception $e) {
-      $error_message = [
-        '#title' => $this->t('Resolve the issue below to continue the upgrade.'),
-        '#theme' => 'item_list',
-        '#items' => [$e->getMessage()],
-      ];
-      $form_state->setErrorByName($database['driver'] . '][0', $this->renderer->renderPlain($error_message));
+      $this->errors[$driver] = $e->getMessage();
+    }
+
+    // Display all errors as a list of items.
+    if ($this->errors) {
+      $this->buildErrorList($this->errors, $form_state);
     }
   }
 
   /**
+   * The #element_validate handler for the source path elements.
+   *
+   * Ensures that entered path can be read.
+   */
+  public function validatePaths($element, FormStateInterface $form_state) {
+    if ($source = $element['#value']) {
+      $msg = $this->t('Unable to read from @title.', ['@title' => $element['#title']]);
+      if (Utility\UrlHelper::isExternal($source)) {
+        try {
+          $this->httpClient->head($source);
+        }
+        catch (TransferException $e) {
+          $this->errors[$element['#name']] = $msg . ' ' . $e->getMessage();
+        }
+      }
+      else {
+        if (!file_exists($source) || (!is_dir($source)) || (!is_readable($source))) {
+          $this->errors[$element['#name']] = $msg;
+        }
+      }
+    }
+  }
+
+  /**
+   * Builds list of errors for display.
+   *
+   * @param array $errors
+   *   Associative array of errors keyed by element name.
+   * @param \Drupal\Core\Form\FormStateInterface $form_state
+   *   The form state.
+   */
+  protected function buildErrorList(array $errors, FormStateInterface $form_state) {
+    $items = [];
+    foreach ($errors as $name => $message) {
+      $form_state->setErrorByName($name);
+      $items[] = $message;
+    }
+
+    $list = [
+      '#title' => $this->t('Resolve all issues below to continue the upgrade.'),
+      '#theme' => 'item_list',
+      '#items' => $items,
+    ];
+    $name = current(array_keys($errors));
+    $form_state->setErrorByName($name . '][0', $this->renderer->renderPlain($list));
+  }
+
+  /**
    * {@inheritdoc}
    */
   public function submitForm(array &$form, FormStateInterface $form_state) {
diff --git a/core/modules/migrate_drupal_ui/tests/src/Functional/MigrateUpgradeExecuteTestBase.php b/core/modules/migrate_drupal_ui/tests/src/Functional/MigrateUpgradeExecuteTestBase.php
index 6cb10e4f9b..852ba96e16 100644
--- a/core/modules/migrate_drupal_ui/tests/src/Functional/MigrateUpgradeExecuteTestBase.php
+++ b/core/modules/migrate_drupal_ui/tests/src/Functional/MigrateUpgradeExecuteTestBase.php
@@ -70,16 +70,35 @@ public function testMigrateUpgradeExecute() {
     // Ensure submitting the form with invalid database credentials gives us a
     // nice warning.
     $this->drupalPostForm(NULL, [$driver . '[database]' => 'wrong'] + $edits, t('Review upgrade'));
-    $session->pageTextContains('Resolve the issue below to continue the upgrade.');
+    $session->pageTextContains('Resolve all issues below to continue the upgrade.');
 
     $this->drupalPostForm(NULL, $edits, t('Review upgrade'));
     // Ensure we get errors about missing modules.
-    $session->pageTextContains(t('Resolve the issue below to continue the upgrade'));
+    $session->pageTextContains(t('Resolve all issues below to continue the upgrade.'));
     $session->pageTextContains(t('The no_source_module plugin must define the source_module property.'));
 
     // Uninstall the module causing the missing module error messages.
     $this->container->get('module_installer')->uninstall(['migration_provider_test'], TRUE);
 
+    // Test the file sources.
+    $this->drupalGet('/upgrade');
+    $this->drupalPostForm(NULL, [], t('Continue'));
+    if ($version == 6) {
+      $paths['d6_source_base_path'] = DRUPAL_ROOT . '/wrong-path';
+    }
+    else {
+      $paths['source_base_path'] = 'https://example.com/wrong-path';
+      $paths['source_private_file_path'] = DRUPAL_ROOT . '/wrong-path';
+    }
+    $this->drupalPostForm(NULL, $paths + $edits, t('Review upgrade'));
+    if ($version == 6) {
+      $session->responseContains('Unable to read from Files directory.');
+    }
+    else {
+      $session->responseContains('Unable to read from Public files directory.');
+      $session->responseContains('Unable to read from Private file directory.');
+    }
+
     // Restart the upgrade process.
     $this->drupalGet('/upgrade');
     $session->responseContains('Upgrade a site by importing its files and the data from its database into a clean and empty new install of Drupal 8.');
