I have term and node migrations from wprdpress to drupal 8 (with pathauto module enabled). I set the url alias in the migration templates like:

  path/alias: source_path
    plugin: default_value
    default_value: 0

Setting the path that way works fine on importing content with drush mi term. But when I update the terms with drush mi term --update a new (the same) path gets inserted into the url_alias table. For example the term with tid 1 gets imported once and updated 2 times there will be the following aliases in url_alias table:

select * from url_alias where source = '/taxonomy/term/1';
| pid  | source           | alias         | langcode |
| 1514 | /taxonomy/term/1 | /term-1-alias | de       |
| 2731 | /taxonomy/term/1 | /term-1-alias | de       |
| 3632 | /taxonomy/term/1 | /term-1-alias | de       |

BTW: I have pathauto module enabled, but uninstalling it results in the same behavior.

2 Answers 2


Looks like a bug in the core path module: https://www.drupal.org/node/2350135


I made the following workaround to avoid the problem:

create a custom process plugin that checks if an url_alias record was already inserted for the $value / node combination. If so, it returns NULL and if not it returns $value:

 * @file
 * Contains \Drupal\your_migrate_module\Plugin\migrate\process\EmptyIfUrlAliasExists.

namespace Drupal\your_migrate_module\Plugin\migrate\process;

use Drupal\Core\Database\Database;
use Drupal\migrate\Annotation\MigrateProcessPlugin;
use Drupal\migrate\MigrateExecutableInterface;
use Drupal\migrate\ProcessPluginBase;
use Drupal\migrate\Row;

 * This process plugin can be used for path/alias fields as long as the following issues are not resolved. It is a workaround for:
 * https://www.drupal.org/node/2350135#comment-9476629
 * https://drupal.stackexchange.com/questions/238393/migrate-duplicate-entries-in-url-alias-after-update-migrations)
 * @MigrateProcessPlugin(
 *   id = "empty_if_url_alias_exists",
 * )
class EmptyIfUrlAliasExists extends ProcessPluginBase
     * {@inheritdoc}
    public function transform(
        MigrateExecutableInterface $migrate_executable,
        Row $row,
    ) {
        // Retrieves a \Drupal\Core\Database\Connection which is a PDO instance
        $db = Database::getConnection();

        $sth = $db->select('url_alias', 'u')
            ->fields('u', ['pid']);
        $and = $sth->andConditionGroup()
            ->condition('u.source', '/node/' . $row->getIdMap()['destid1'])
            ->condition('u.alias', $value);
        $data = $sth->execute();

        $results = $data->fetch(\PDO::FETCH_NUM);

        //when no url_alias record found, return the url, so it can be added.
        if ($results === false || count($results) === 0) {
            return $value;
        //when an url_alias record is already present, return null, so the migration does not add it again
        return null;

Then in the process part of my node migration yml, I use the following:

     plugin: default_value
     default_value: 0 # Disable pathauto.
      plugin: empty_if_url_alias_exists
      source: public_url
      plugin: skip_on_empty
      method: process

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.