Why is my migrate source plugin (d7_file) not found for my migration? I'm trying to write a migration for files from an old D7 site to a new D8 site, roughly following the instructions at https://www.previousnext.com.au/blog/migrating-drupal-7-file-entities-drupal-8-media-entities.

I have a myproject_migration module which includes the migration in its install folder.

myproject_migration.info.yml:

name: MyProject Migration
description: Migrations for existing MyProject content.
package: myproject
type: module
core: '8.x'
dependencies:
  - file
  - migrate
  - migrate_plus
  - migrate_source_csv
  - migrate_tools


config/install/migrate_plus.migration.furniture_files.yml:

id: files
label: Files from the old D7 site.
migration_group: myproject
dependencies:
  enforced:
    module:
      - myproject_migration
      - file
source:
  plugin: d7_file
  scheme: public
  constants:
    source_base_path: /
process:
  fid: fid
  filename: filename
  source_full_path:
    -
      plugin: concat
      delimiter: /
      source:
        - constants/source_base_path
        - filepath
    -
      plugin: urlencode
  uri:
    plugin: file_copy
    source:
      - '@source_full_path'
      - uri
  filemime: filemime
  status: status
  created: timestamp
  changed: timestamp
  #uid: uid
destination:
  plugin: 'entity:file'


I enable the module; run drush migrate-status and get:


exception 'Drupal\Component\Plugin\Exception\PluginNotFoundException' 
...with message 'The "d7_file" plugin does not exist.' 
...in /var/www/myproject/docroot/core/lib/Drupal/Component/Plugin/Discovery/DiscoveryTrait.php:52
Stack trace:
#0 /var/www/myproject/docroot/core/lib/Drupal/Component/Plugin/Discovery/DiscoveryCachedTrait.php(25):
Drupal\Core\Plugin\DefaultPluginManager->doGetDefinition(Array, 'd7_file', true)
#1 /var/www/myproject/docroot/core/modules/migrate/src/Plugin/MigratePluginManager.php(53):
Drupal\Core\Plugin\DefaultPluginManager->getDefinition('d7_file')
#2 /var/www/myproject/docroot/core/modules/migrate/src/Plugin/Migration.php(335):
Drupal\migrate\Plugin\MigratePluginManager->createInstance('d7_file', Array, Object(Drupal\migrate\Plugin\Migration))
#3 /var/www/myproject/docroot/modules/contrib/migrate_tools/migrate_tools.drush.inc(471): Drupal\migrate\Plugin\Migration->getSourcePlugin()
...


I've been importing updates to this config with drush config-import --partial -y --source=modules/custom/myproject_migration/config/install/.

I can see the plugin in core\modules\file\src\Plugin\migrate\source\d7\File.php, with the id "d7_file". Running through the checklist at https://www.drupal.org/docs/8/api/migrate-api/migrate-source-plugins - it implements MigrateSourceInterface; it's annotated with @MigrateSource; it's in in the namespace subdir Plugin\migrate\source under the "file" namespace. So it's definitely there, and everything looks right, it's just not found.
Make sure the migrate_drupal module is enabled. (I can't be sure that's the reason, but it's the first one I stumbled over when I reproduced this locally.)

The reason this isn't easy to see:

Migrate plugins have multiple providers (which must all be enabled to use the plugin), and the relevant plugin managers actually use their own discovery which automatically infers providers from the parent class namespace. So the d7_file plugin has the providers "file" and "migrate_drupal" as it is provided by the file module but extends a class from the migrate_drupal module.

In effect, migrate's multi-provider thing adds "invisible" dependencies which silently remove the plugin when the required modules aren't installed.