Skip to content

Importing Models

ECA models can be imported into your Drupal site in several ways. This guide covers all available import methods, explains common issues that may arise during import, and provides solutions for resolving them.

Import methods

Since Drupal 10.3, the recommended way to import models from the ECA Library is via recipes. Each library model is available as a Composer package that can be applied as a Drupal recipe.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# Require the recipe package
composer require drupal-eca-recipe/eca_lib_XXXX

# Apply the recipe with Drush (version 13 or later):
drush recipe ../recipes/eca_lib_XXXX

# Or apply the recipe without Drush:
cd web && php core/scripts/drupal recipe ../recipes/eca_lib_XXXX

# Rebuilding caches is optional, sometimes required:
drush cr

Replace XXXX with the library model number. Each library model page shows the exact commands to use.

Tip

Recipes handle dependencies automatically. If the model requires additional configuration entities (e.g. content types, fields, or vocabularies), the recipe will create them for you.

What a recipe contains is decided by the model it was generated from. For the settings that control that, and for why some configuration has to be declared on the model before it travels with the recipe, see Exporting a model as a recipe.

Using the ECA admin UI

Models can also be imported manually through the ECA admin interface at /admin/config/workflow/eca:

  1. Click the Import button in the top right corner.
  2. Select the file to import.
  3. Click Import to validate and import the model.

The form offers three types, selected with the Type radio button:

Model
A single eca.eca.[MODEL-ID].yml config file. This is the whole model: everything ECA needs at runtime lives in that one file, and you do not need a modeler to import it. See ECA model config files for details. Import checks that every module and config entity listed under the file's dependencies key already exists on your site.
Raw
The native file of a visual modeler, for example the JSON of the Workflow Modeler or the XML of BPMN.iO. Select the matching modeler from the Modeler list on the same form, because ECA derives the model from the raw data. The file extension has to match the modeler you select.
Archive

A .tar.gz archive previously exported from another Drupal site or downloaded from the ECA Library. The archive contains:

  • dependencies.yml — metadata listing required config entities and modules
  • eca.eca.[MODEL-ID].yml — the model config entity
  • modeler_api.data_model.[STORAGE-ID].yml — the raw modeler data, only when the model uses the separate storage strategy
  • optionally, additional config entities that the model depends on

Note

When importing an archive, do not rename the file. The filename is validated during import and must match the pattern [MODELER-TYPE]-[MODEL-ID].tar.gz.

Using Drupal's configuration management

ECA models are standard Drupal configuration. You can also deploy them through Drupal's configuration synchronization system by placing the model config file (eca.eca.[MODEL-ID].yml) into your configuration sync directory and running a config import:

1
drush config:import

Only models that store their raw modeler data with the separate strategy have a companion modeler_api.data_model.[STORAGE-ID].yml file. Where it exists, deploy it alongside the model.

This is particularly useful for deploying models from a development environment to production. See also the recommended setup for production sites.

Troubleshooting import failures

Sometimes, importing a model may fail. Below are the most common causes and their solutions.

Existing entities prevent import

Symptom: The import fails with a message similar to:

The import failed due to the following reason: There were errors validating the config synchronization. Entities exist of type Content and Content type Basic page. These entities need to be deleted before importing.

Cause: The model archive includes configuration for entities such as content types, vocabularies or fields. If those entities already exist on your site with content attached to them, Drupal's configuration validation rejects the import because it would overwrite existing configuration that has dependent data.

Solutions:

  1. Check for conflicting entities. Compare the configuration in the archive with what already exists on your site. If the existing configuration matches what the model expects, the import may succeed after removing the conflicting config entities from the archive. Extract the archive, remove the unnecessary files, update dependencies.yml accordingly, and repackage it.

  2. Delete conflicting content first. If the existing entities contain test data or content you do not need, delete the content and then the configuration entities before retrying the import.

  3. Import the model file on its own. Instead of importing the full archive, extract it and import just the eca.eca.[MODEL-ID].yml file with the Model type. This skips the bundled dependency configuration, so it works when all of those dependencies already exist on your site in a compatible setup.

  4. Use the recipe method. Recipes handle existing configuration more gracefully. If the configuration already exists and is compatible, the recipe will skip creating it and only add the ECA model.

Tip

For more context on this issue, see drupal.org issue #3381483.

Missing required modules

Symptom: The import fails because one or more required modules are not enabled.

Cause: The model uses plugins provided by modules that are not installed on your site. The dependencies.yml file in the archive lists all required modules.

Solution: Enable the required modules before importing:

1
2
3
# Check which modules are required by extracting the archive
# and reading the dependencies.yml file, then enable them:
drush en module_name_1 module_name_2

When using the recipe method, missing modules are listed as Composer dependencies. Running composer require for the recipe package will automatically install the required modules.

Modeler not available

Symptom: The model imports but you cannot edit it, or a Raw import fails because ECA cannot parse the file.

Cause: The model was created with a specific modeler (e.g. the Workflow Modeler or BPMN.iO), and that modeler is not enabled on your site. Only the Raw type needs a modeler to import at all, because it derives the model from the modeler's own data. A Model or Archive import succeeds without one, but you can only edit the result once the modeler is available.

Solution: Enable the modeler that was used to create the model. All ECA Library models are built with the Workflow Modeler, so enabling eca_ui and modeler is sufficient for library models:

1
drush en eca_ui modeler

Archive filename has been changed

Symptom: The import fails during file validation.

Cause: The archive file was renamed after export. ECA validates the filename to extract the modeler type and model ID.

Solution: Restore the original filename matching the pattern [MODELER-TYPE]-[MODEL-ID].tar.gz. If you do not know the original name, extract the archive and check the config filenames inside — the model ID is part of the eca.eca.[MODEL-ID].yml filename.

Configuration validation errors

Symptom: The import fails with generic configuration validation errors.

Cause: This can happen when the model was created on a different version of Drupal or ECA, and there are schema differences between versions.

Solution:

  1. Ensure you are running a compatible version of ECA. Check the model's documentation or the library page for version requirements.
  2. Update ECA to the latest version: composer update drupal/eca
  3. If the issue persists, extract the archive and import just the eca.eca.[MODEL-ID].yml file with the Model type. This helps when the schema difference sits in one of the bundled dependency config entities rather than in the model itself.

A missing configuration schema leaves data untyped

Symptom: On most sites, nothing. The recipe or the config import applies in full and the site works. On a development site running the current core development.services.yml, a warning is logged and shown that names the configuration object and the key without a schema. Only on a development site that still carries an older or hand-written file does the save fail outright, with a non-zero exit status.

Cause: Drupal casts a configuration value to its declared type as the object is saved, and only where a schema declares that type. Without a schema there is nothing to cast against, so the value is stored exactly as it was set:

1
2
with schema:    set string "1" -> stored as true  (boolean)
without schema: set string "1" -> stored as '1'   (string)

Nothing rejects that value later either. For a configuration object with no schema, hasConfigSchema() returns false, typed data resolves to Drupal\Core\Config\Schema\Undefined, and validation reports zero violations. The result is not invalid configuration. It is configuration that validation cannot judge, so no later check flags it.

The class the site's development.services.yml registers for config.schema_checker decides which of three things happens next. It is the only subscriber to the config save event that looks at schema at all:

Registered class Effect on the save What the operator sees
No development.services.yml, as on production Applies in full, stored untyped Nothing
LenientConfigSchemaChecker, the current core scaffold Applies in full, stored untyped A warning, logged and shown
ConfigSchemaChecker, in older or hand-written files Aborts the save and the rest of the recipe A hard failure, non-zero exit status

The first two rows are the normal case, and there the recipe applies entirely. LenientConfigSchemaChecker catches the SchemaIncompleteException and only warns, so listeners registered after it still run and the value reads back intact. Without a development.services.yml no check runs at all. The cost in both rows is untyped and unvalidated data, not a step that failed to happen.

The third row is the case that stops work, and it is what older sites still have. ConfigSchemaChecker lets SchemaIncompleteException escape from the config save event, and core dispatches that event after writing the data:

1
2
3
$this->storage->write($this->name, $this->data);
// ...
$this->eventDispatcher->dispatch(new ConfigCrudEvent($this), $event_name);

The write has already happened, but everything after it is abandoned: postSave(), entity update hooks, static cache resets, and the rest of the recipe's configuration step. That failure is loud rather than silent, because RecipeCommand catches the exception, attempts a rollback, and throws it again.

Solution:

  1. Ship the schema in the same change as the keys it describes. Casting happens on save and never on read, so the first save fixes the stored type permanently. A value written before its schema existed still reads back with the old type once the schema is added, and still reports zero violations. Adding the schema afterwards does not repair data that is already on disk.
  2. Read the site log after applying a recipe on a development site. A config_schema entry names the configuration object and the key that has no schema.
  3. Where the strict checker did abort a step, apply the recipe again on a clean site rather than on the half-applied one, because the partial write from the aborted attempt is still there.

Best practices for importing

  • Back up your site before importing models, especially on production environments.
  • Review the model before importing. Each library model page includes a visual representation of the model and a list of its dependencies.
  • Use a development environment to test imported models before deploying them to production.
  • Prefer recipes when importing library models — they handle dependencies automatically and are more resilient to existing configuration.
  • Keep your ECA installation up to date to ensure compatibility with the latest library models.