Magento2: URL key for specified store already exists in Magento 2.1.1

Created on 20 Sep 2016  Â·  100Comments  Â·  Source: magento/magento2

I am facing "URL key for specified store already exists" error when i am trying to update existing category name as its appearing in some categories.

I am using Magento 2.1.1.
I have read so many articales where it stated that it is solved in magento 2.1 version but its appearing again. Let me know
Please help me to resolve the issue.

Thanks

Preconditions

Magento 2.1.1

Steps to reproduce

Try to update the name of existing category as its appearing in some categories

Expected result

Category's name is updated

Actual result

"URL key for specified store already exists" error

CatalogUrlRewrite Format is valid Ready for Work bug report

Most helpful comment

When will this be finally fixed? issue is up since more than a year now?!

All 100 comments

Hi @sanjayjethva, Please format your issue description according to the Issue reporting guidelines.

This problem happens when you have product and category with the same url key.

Example:

1.- Create Category: Energy Products(URL Key:energy-products)
2.- Create Sub Category Category: Stacker 2 Energy Shots(URL Key:stacker-2-energy-shots)
3.- Create Grouped Product: Stacker 2 Energy Shots(URL Key:stacker-2-energy-shots)
4.- Add Product "Stacker 2 Energy Shots" to Category "Energy Products" for example

Error: URL key for specified store already exists.
image

image

I can confirm, same problem on Magento 2.1.1

Hello @mgomez-dgt
Thanks for your answer but problem still exist if i can change the category url or name to say "test" or "demo". I am choosing random name but still it displays same error.
I am facing the issue when i change category name.

Thanks and let me know

same problem while updating an product with category changes

Similiar problem here, but touches product-category relations. Removing product-category assignment allows you to save the product without having "URL key for specified store already exists." (but of course is not desirable for any store owners out there).
If it helps anyone debugging this this is the URL Rewrites that didn't allow me to add product unless categories were unassigned:

mysql> select * from url_rewrite\G;
*************************** 1. row ***************************
  url_rewrite_id: 1
     entity_type: cms-page
       entity_id: 1
    request_path: no-route
     target_path: cms/page/view/page_id/1
   redirect_type: 0
        store_id: 1
     description: NULL
is_autogenerated: 1
        metadata: NULL
*************************** 2. row ***************************
  url_rewrite_id: 2
     entity_type: cms-page
       entity_id: 2
    request_path: home
     target_path: cms/page/view/page_id/2
   redirect_type: 0
        store_id: 1
     description: NULL
is_autogenerated: 1
        metadata: NULL
*************************** 3. row ***************************
  url_rewrite_id: 3
     entity_type: cms-page
       entity_id: 3
    request_path: enable-cookies
     target_path: cms/page/view/page_id/3
   redirect_type: 0
        store_id: 1
     description: NULL
is_autogenerated: 1
        metadata: NULL
*************************** 4. row ***************************
  url_rewrite_id: 4
     entity_type: cms-page
       entity_id: 4
    request_path: privacy-policy-cookie-restriction-mode
     target_path: cms/page/view/page_id/4
   redirect_type: 0
        store_id: 1
     description: NULL
is_autogenerated: 1
        metadata: NULL
*************************** 5. row ***************************
  url_rewrite_id: 242
     entity_type: product
       entity_id: 14
    request_path: /red-wine/testingadmin-simple.html
     target_path: catalog/product/view/id/14/category/11
   redirect_type: 0
        store_id: 2
     description: NULL
is_autogenerated: 0
        metadata: a:1:{s:11:"category_id";s:2:"11";}
*************************** 6. row ***************************
  url_rewrite_id: 263
     entity_type: category
       entity_id: 6
    request_path: whiskey.html
     target_path: catalog/category/view/id/6
   redirect_type: 0
        store_id: 2
     description: NULL
is_autogenerated: 1
        metadata: NULL
*************************** 7. row ***************************
  url_rewrite_id: 264
     entity_type: category
       entity_id: 8
    request_path: whiskey/.html
     target_path: catalog/category/view/id/8
   redirect_type: 0
        store_id: 2
     description: NULL
is_autogenerated: 1
        metadata: NULL
*************************** 8. row ***************************
  url_rewrite_id: 265
     entity_type: category
       entity_id: 6
    request_path: .html
     target_path: catalog/category/view/id/6
   redirect_type: 0
        store_id: 1
     description: NULL
is_autogenerated: 1
        metadata: NULL
*************************** 9. row ***************************
  url_rewrite_id: 266
     entity_type: category
       entity_id: 8
    request_path: whiskey/.html
     target_path: catalog/category/view/id/8
   redirect_type: 0
        store_id: 1
     description: NULL
is_autogenerated: 1
        metadata: NULL
*************************** 10. row ***************************
  url_rewrite_id: 351
     entity_type: product
       entity_id: 28
    request_path: wine.html
     target_path: catalog/product/view/id/28
   redirect_type: 0
        store_id: 2
     description: NULL
is_autogenerated: 1
        metadata: NULL
*************************** 11. row ***************************
  url_rewrite_id: 352
     entity_type: product
       entity_id: 28
    request_path: wine.html
     target_path: catalog/product/view/id/28
   redirect_type: 0
        store_id: 1
     description: NULL
is_autogenerated: 1
        metadata: NULL
*************************** 12. row ***************************
  url_rewrite_id: 447
     entity_type: product
       entity_id: 45
    request_path: 1.html
     target_path: catalog/product/view/id/45
   redirect_type: 0
        store_id: 2
     description: NULL
is_autogenerated: 1
        metadata: NULL
*************************** 13. row ***************************
  url_rewrite_id: 448
     entity_type: product
       entity_id: 45
    request_path: 1.html
     target_path: catalog/product/view/id/45
   redirect_type: 0
        store_id: 1
     description: NULL
is_autogenerated: 1
        metadata: NULL
*************************** 14. row ***************************
  url_rewrite_id: 485
     entity_type: product
       entity_id: 51
    request_path: 5.html
     target_path: catalog/product/view/id/51
   redirect_type: 0
        store_id: 2
     description: NULL
is_autogenerated: 1
        metadata: NULL
*************************** 15. row ***************************
  url_rewrite_id: 486
     entity_type: product
       entity_id: 51
    request_path: 5.html
     target_path: catalog/product/view/id/51
   redirect_type: 0
        store_id: 1
     description: NULL
is_autogenerated: 1
        metadata: NULL
*************************** 16. row ***************************
  url_rewrite_id: 487
     entity_type: product
       entity_id: 52
    request_path: 6.html
     target_path: catalog/product/view/id/52
   redirect_type: 0
        store_id: 2
     description: NULL
is_autogenerated: 1
        metadata: NULL
*************************** 17. row ***************************
  url_rewrite_id: 488
     entity_type: product
       entity_id: 52
    request_path: 6.html
     target_path: catalog/product/view/id/52
   redirect_type: 0
        store_id: 1
     description: NULL
is_autogenerated: 1
        metadata: NULL
*************************** 18. row ***************************
  url_rewrite_id: 489
     entity_type: product
       entity_id: 53
    request_path: 7.html
     target_path: catalog/product/view/id/53
   redirect_type: 0
        store_id: 2
     description: NULL
is_autogenerated: 1
        metadata: NULL
*************************** 19. row ***************************
  url_rewrite_id: 490
     entity_type: product
       entity_id: 53
    request_path: 7.html
     target_path: catalog/product/view/id/53
   redirect_type: 0
        store_id: 1
     description: NULL
is_autogenerated: 1
        metadata: NULL
*************************** 20. row ***************************
  url_rewrite_id: 491
     entity_type: product
       entity_id: 54
    request_path: 8.html
     target_path: catalog/product/view/id/54
   redirect_type: 0
        store_id: 2
     description: NULL
is_autogenerated: 1
        metadata: NULL
*************************** 21. row ***************************
  url_rewrite_id: 492
     entity_type: product
       entity_id: 54
    request_path: 8.html
     target_path: catalog/product/view/id/54
   redirect_type: 0
        store_id: 1
     description: NULL
is_autogenerated: 1
        metadata: NULL
*************************** 22. row ***************************
  url_rewrite_id: 493
     entity_type: product
       entity_id: 55
    request_path: 888.html
     target_path: catalog/product/view/id/55
   redirect_type: 0
        store_id: 2
     description: NULL
is_autogenerated: 1
        metadata: NULL
*************************** 23. row ***************************
  url_rewrite_id: 494
     entity_type: product
       entity_id: 55
    request_path: 888.html
     target_path: catalog/product/view/id/55
   redirect_type: 0
        store_id: 1
     description: NULL
is_autogenerated: 1
        metadata: NULL
*************************** 24. row ***************************
  url_rewrite_id: 495
     entity_type: cms-page
       entity_id: 5
    request_path: test-article
     target_path: cms/page/view/page_id/5
   redirect_type: 0
        store_id: 2
     description: NULL
is_autogenerated: 1
        metadata: NULL
*************************** 25. row ***************************
  url_rewrite_id: 496
     entity_type: cms-page
       entity_id: 5
    request_path: test-article
     target_path: cms/page/view/page_id/5
   redirect_type: 0
        store_id: 1
     description: NULL
is_autogenerated: 1
        metadata: NULL
*************************** 26. row ***************************
  url_rewrite_id: 567
     entity_type: category
       entity_id: 19
    request_path: root-catalog.html
     target_path: catalog/category/view/id/19
   redirect_type: 0
        store_id: 2
     description: NULL
is_autogenerated: 1
        metadata: NULL
*************************** 27. row ***************************
  url_rewrite_id: 568
     entity_type: category
       entity_id: 19
    request_path: root-catalog.html
     target_path: catalog/category/view/id/19
   redirect_type: 0
        store_id: 1
     description: NULL
is_autogenerated: 1
        metadata: NULL
*************************** 28. row ***************************
  url_rewrite_id: 258507
     entity_type: product
       entity_id: 72
    request_path: some-testing-product.html
     target_path: catalog/product/view/id/72
   redirect_type: 0
        store_id: 2
     description: NULL
is_autogenerated: 1
        metadata: NULL
*************************** 29. row ***************************
  url_rewrite_id: 258508
     entity_type: product
       entity_id: 72
    request_path: some-testing-product.html
     target_path: catalog/product/view/id/72
   redirect_type: 0
        store_id: 1
     description: NULL
is_autogenerated: 1
        metadata: NULL
29 rows in set (0.00 sec)

It seems like there's something wrong with category update mechanism.

I went ahead saving categories one by one and pinpointed the troubling category to:
/catalog/category/edit/id/10/

and seen there's really no url in database so made it:

insert into url_rewrite VALUES (NULL,'category',10,'wines.html','catalog/category/view/id/10',0,1,NULL,1,NULL);
insert into catalog_category_entity_varchar VALUES (NULL,117,0,10,'wines'); (117 - url_key)
insert into catalog_category_entity_varchar VALUES (NULL,118,0,10,'wines'); (118 - url_path)

then run:
php bin/magento indexer:reindex

now the url would appear in the admin edit form but of course still after trying to save it:
URL key for specified store already exists.

I went ahead and added url keys manually to the DB and updated url_rewrite manually aswell. still can't save that product with categories assigned...

We need to go deeper then....
In vendor/magento/module-url-rewrite/Model/Storage/AbstractStorage.php
added some additional info:

throw new \Magento\Framework\Exception\AlreadyExistsException(
                __('URL key for specified store already exists - '.$e->getMessage() )
            );

and that got me the error I needed:
SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '/testing-products.html-2' for key 'URL_REWRITE_REQUEST_PATH_STORE_ID', query was: INSERT INTOurl_rewrite(redirect_type,is_autogenerated,metadata,description,entity_type,entity_id,request_path,target_path,store_id) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?), (?, ?, ?, ?, ?, ?, ?, ?, ?), (?, ?, ?, ?, ?, ?, ?, ?, ?), (?, ?, ?, ?, ?, ?, ?, ?, ?), (?, ?, ?, ?, ?, ?, ?, ?, ?), (?, ?, ?, ?, ?, ?, ?, ?, ?), (?, ?, ?, ?, ?, ?, ?, ?, ?), (?, ?, ?, ?, ?, ?, ?, ?, ?)
wait what? I already fixe duniqueness of my urls....

Considering the result of
show index from url_rewrite where non_unique = 0\G; that says we only make use of target_path and store_id I stripped the data the app is trying to insert:

array (
  0 => 
  array (
    'request_path' => 'testing-products.html',
    'target_path' => 'catalog/product/view/id/84',
    'store_id' => '2',
  ),
  1 => 
  array (
    'request_path' => 'wines/testing-products.html',
    'target_path' => 'catalog/product/view/id/84/category/10',
    'store_id' => '2',
  ),
  2 => 
  array (
    'request_path' => '/testing-products.html',
    'target_path' => 'catalog/product/view/id/84/category/1',
    'store_id' => '2',
  ),
  3 => 
  array (
    'request_path' => '/testing-products.html',
    'target_path' => 'catalog/product/view/id/84/category/2',
    'store_id' => '2',
  ),
  4 => 
  array (
    'request_path' => 'testing-products.html',
    'target_path' => 'catalog/product/view/id/84',
    'store_id' => '1',
  ),
  5 => 
  array (
    'request_path' => 'wines/testing-products.html',
    'target_path' => 'catalog/product/view/id/84/category/10',
    'store_id' => '1',
  ),
  6 => 
  array (
    'request_path' => '/testing-products.html',
    'target_path' => 'catalog/product/view/id/84/category/1',
    'store_id' => '1',
  ),
  7 => 
  array (
    'request_path' => '/testing-products.html',
    'target_path' => 'catalog/product/view/id/84/category/2',
    'store_id' => '1',
  ),
)

So the problem seems to be in categories 1 & 2 which, through the admin panel, I cannot update url keys for. And that leads us to some hints for why custom imports fail here and why shop, where the customer accidentally removed his root category (which was later readded) fails.

Edit: dirty fix is changing
vendor/magento/module-url-rewrite/Model/Storage/DbStorage.php
from

    protected function doReplace($urls)
    {
        foreach ($this->createFilterDataBasedOnUrls($urls) as $type => $urlData) {
            $urlData[UrlRewrite::ENTITY_TYPE] = $type;
            $this->deleteByData($urlData);
        }
        $data = [];
        foreach ($urls as $url) {
            $data[] = $url->toArray();
        }
        $this->insertMultiple($data);
    }

into

    protected function doReplace($urls)
    {
        foreach ($this->createFilterDataBasedOnUrls($urls) as $type => $urlData) {
            $urlData[UrlRewrite::ENTITY_TYPE] = $type;
            $this->deleteByData($urlData);
        }
        $data = [];
        foreach ($urls as $url) {
            $data[] = $url->toArray();
        }

         /* FIXME: Get rid of rewrite for root Magento category to unduplicate things
          * @see: https://github.com/magento/magento2/issues/6671 */
        foreach($data as $key =>$info){
                if(isset($info['target_path']) && stristr($info['target_path'],'/category/1') && $info['entity_type']=='product'){
                        unset($data[$key]);
                }
        }

        $this->insertMultiple($data);
    }

M2 team: please fix root category handling and that should fix those.

@miakusha :point_up: there's your update ;)

I'm having the same issue as well. Is it being fixed, so should I just do the dirty fix to get the ball rolling?

I tried to update DbStorage.php per @janmyszkier recommendation, but the error URL key for specified store already exists. still thrown after I tried to update the category name.

Can confirm this is happening with 2.1.2 EE as well.

@frostshoxx it's like your root category has a different ID than the one in @janmyszkier's example code

Confirmed in M2.1.2

I have 2 categories that have similar sub-category names (For example foo/bar, goo/bar). 'bar' is considered a duplicate key.

Fun fact: truncating the url_rewrite table did solve the problem for me.

I managed to fix this in the end, I would recommend _not_ emptying your url_rewrite table.

We had multiple stores, and products from store A were associated to categories under store B. At a high level this is what I can tell was happening:

  • Store A had category X with multiple products
  • Store B had product Y that was somehow added to category X in Store A
  • When Magento generates category level rewrites, it goes through every product in each store's category. It found product Y in category X and generated a product level rewrite for it (this is wrong, because the product was not available in Store A)
  • When Magento then tries to generate product level rewrites it attempts to generate the product level rewrite for product Y again it hits the "URL key for specified store already exists" error, because in the previous step it had been generated already.

@jameshalsall How did you manage to fix this issue in the end?

Hi guys,

Let's try with a workaround in reply from @quynhvv in here:
https://github.com/magento/magento2/issues/7298

Regards,
Mall.

:-1: for @magento-team for leaving this issue unresolved for so long with not even a workaround.

@frostshoxx I removed the associations of products to categories that were cross-store, if that makes sense.

EDIT: I think this could be a problem with the save + duplicate feature, when you're editing a product from one store and then duplicate it to the other store it may keep the category associations from the original store.

The url regeneration process is large/implicit and complex to keep all the main entities in e-commerce industry (products and categories) accessible to customers.

Flow

The flow is next:

  • category entity itself is processed and all the changes are saved to DB (in terms of active transaction)
  • then afterSave event is dispatched (this event is dispatched to any entity in Magento 2 if child of AbstractModel)
  • urlProcessing is run according to observer configuration in Magento_CatalogUrlRewrite module:
<event name="catalog_category_save_after">
    <observer name="process_url_rewrite_saving" instance="Magento\CatalogUrlRewrite\Observer\CategoryProcessUrlRewriteSavingObserver"/>
</event>
  • process generates canonical category URL rewrite
  • the process runs through all the products (direct child products as well as products in subcategories)
  • process generates current URL rewrites (301 redirects)
  • process generates anchor URL rewrites
  • then all generated rewrites is combined into one array via array_merge
  • process generates one INSERT query with generated rewrites as binding for it
  • logically process running the query execution

Actual problem

The error shown on frontend is "URL key for specified store already exists." but actual error message which is generated by DB engine is next:
SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '[SOME_URL_PATH]' for key 'URL_REWRITE_REQUEST_PATH_STORE_ID'

Used environment

Environment is next:

  • Magento EE 2.1.2
  • Apache/nginx

Causes explanation

The problem is caused by using of array_merge (1st) for combining all the url rewrites generated and by anchor URL rewrites generation procedure (2nd):

  • before array_merge
    before array_merge
  • after array_merge
    after array_merge

Second is using categoryRepository in internals for obtaining category objects which opens a possibility to use inconsistent/outdated data and first one makes it possible to overwrite correctly generated data with wrong data from anchor URL generation.

In our case the problem was and still is with product rome-umbrella-lane which belonds to the category _women's accessories_ (URL key is womes-s-accessories). When the user fills new url_path (women-accessories) the the whole process is run and during the anchor generation one products category is in fact child category for edited one:
vendor/magento/module-catalog-url-rewrite/Model/ProductUrlRewriteGenerator.php

protected function generateForSpecificStoreView($storeId, $productCategories)
...
$urls = array_merge(
            $this->canonicalUrlRewriteGenerator->generate($storeId, $this->product),
            $this->categoriesUrlRewriteGenerator->generate($storeId, $this->product, $this->productCategories),
            $this->currentUrlRewritesRegenerator->generate($storeId, $this->product, $this->productCategories),
            $this->getAnchorUrlRewriteGenerator()->generate($storeId, $this->product, $this->productCategories)
        );
...

scarves category is child of women-s-accessories and parent category is marked as anchor:
vendor/magento/module-catalog-url-rewrite/Model/Product/AnchorUrlRewriteGenerator.php

public function generate($storeId, Product $product, ObjectRegistry $productCategories)
...
$anchorCategoryIds = $category->getAnchorsAbove();
            if ($anchorCategoryIds) {
                foreach ($anchorCategoryIds as $anchorCategoryId) {
                    //TODO add check is anchored category is edited category and url_path updated
                    $anchorCategory = $this->categoryRepository->get($anchorCategoryId);
...

In $this->categoryRepository->get($anchorCategoryId) category object is fetched from cache:
vendor/magento/module-catalog/Model/CategoryRepository.php

/**
     * {@inheritdoc}
     */
    public function get($categoryId, $storeId = null)
    {
        $cacheKey = null !== $storeId ? $storeId : 'all';
        //if (!isset($this->instances[$categoryId][$cacheKey])) {
            /** @var Category $category */
            $category = $this->categoryFactory->create();
            if (null !== $storeId) {
                $category->setStoreId($storeId);
            }
            $category->load($categoryId);
            if (!$category->getId()) {
                throw NoSuchEntityException::singleField('id', $categoryId);
            }
            $this->instances[$categoryId][$cacheKey] = $category;
        //}
        return $this->instances[$categoryId][$cacheKey];
    }

Problem cause

product is assigned directly to edited category (while editing url_key) and assigned to one of child category and edited category marked as anchor.

Options of resolving for Magento Team

The solution is not clear at first glance but there are few options:

  • get rid of cache usage for urlGeneration (can affect the time and speed drastically)
  • add a feature to flush category cache directly before urlGeneration procedure (will not affect the speed dramatically but for now categoryRepository doesn't have a feature to flush protected _instances field)

Options for us until Magento 2 release

One of the options which is available for client project developers - apply complex solution with few rewrites via preference for categoryRepository to add instances cache invalidation method and anchorURLRewriteGeneration with usage of added method but obviously this isn't recommended at all bc can affect different parts of the functionality.

Hope this will help to fix this issue finally.

Currently I'm patching these issues (incorrect anchor URLs and not generating URLs for multiple stores) by:

  1. Replacing $storeId=$category->getStoreId() in module-catalog-url-rewrite/Observer/UrlRewriteHandler.php with $storeId=0. This then works like the category URL generation and iterates over the stores. Just getting the current store only creates (and deletes) links for the current store
  2. Commenting out $this->getAnchorUrlRewriteGenerator()->generate($storeId, $this->product, $this->productCategories) in module-catalog-url-rewrite/Model/ProductUrlRewriteGenerator.php as I have yet to find the situation where this is actually needed.

Obviously I now need to make these into plugins or preferences, but can anyone see a problem with these fixes?

After my changes the errors go away in some cases. Still getting the error sometimes. Trying to track down exactly when.

I'm trying it local now as well. But the weird part is: earlier, when I truncated the url_rewrite-table, the problem was gone, but now when I truncate the table and re-save the category I get the same error. I've looked in the database and there are no other categories that share the same URL key.

@kanduvisla if you look at the example you'll see that I didn't have them either and the error was there because it tried to INSERT them (which failed). not because they were already in the database.

i was getting the same error, i fixed mine by removing duplicated data from the product url-keys.
What i saw was, that i had 2 or more products with the same url-key, under the same categorie.

I tried the fix mentioned by janmyszkier. At first I could save the category. On a second save I get the error again :(

If anybody wants to test this possible fix and give me some feedback, that would be great! In my case it fixed our url rewrite issues (based on M2 CE 2.1.2 codebase, module-catalog-url-rewrite):
diff diff --git a/Model/Product/AnchorUrlRewriteGenerator.php b/Model/Product/AnchorUrlRewriteGenerator.php index 972b5c0..8845c7a 100644 --- a/Model/Product/AnchorUrlRewriteGenerator.php +++ b/Model/Product/AnchorUrlRewriteGenerator.php @@ -55,7 +55,7 @@ public function generate($storeId, Product $product, ObjectRegistry $productCate $anchorCategoryIds = $category->getAnchorsAbove(); if ($anchorCategoryIds) { foreach ($anchorCategoryIds as $anchorCategoryId) { - $anchorCategory = $this->categoryRepository->get($anchorCategoryId); + $anchorCategory = $this->categoryRepository->get($anchorCategoryId, $storeId); $urls[] = $this->urlRewriteFactory->create() ->setEntityType(ProductUrlRewriteGenerator::ENTITY_TYPE) ->setEntityId($product->getId()) diff --git a/Model/ProductScopeRewriteGenerator.php b/Model/ProductScopeRewriteGenerator.php index 94464ec..0cba5cb 100644 --- a/Model/ProductUrlRewriteGenerator.php +++ b/Model/ProductUrlRewriteGenerator.php @@ -138,7 +138,12 @@ public function generateForGlobalScope($productCategories) if (!$this->isGlobalScope($id) && !$this->storeViewService->doesEntityHaveOverriddenUrlKeyForStore($id, $productId, Product::ENTITY) ) { - $urls = array_merge($urls, $this->generateForSpecificStoreView($id, $productCategories)); + // before loading the category collection by looping it, clone it and set the correct store id, + // so we get the correct url_path & url_key for that specific store id + $storeSpecificProductCategories = clone $productCategories; + $storeSpecificProductCategories->setStoreId($id); + + $urls = array_merge($urls, $this->generateForSpecificStoreView($id, $storeSpecificProductCategories)); } }

@hostep I used your fixed and it worked for created new categories, but it didn't work when i tried to go back to the original category e.g

test -> test1 = worked
test1 -> test2 = worked
test2 -> test = same error message

I have similar issue when I try to rename the mane of the category in Store View (M2.1.0)
Also it makes the error only for certain store view, it's not possible to change the name of the category to something completely different.

Does anybody have a few "test" queries for the Db to help find the offending category/product that is causing this error?
Also, are the category names taken into context when saving, or is it just the url_key that is important?

Reason I ask, I've made sure all of my categories have unique url key's, but several have the same text name (they reside under different sub-categories so are actually different).

Maybe would be helpful for someone. I've faced same issue on fresh install of 2.1.2 updated to 2.1.3 later. Problem was that I wasn't able to save any category with previously imported products, exception was thrown every time. The problem was that category with ID 1 (Root Catalog) had attribute is_anchor set to 1. This way magento tried to create doubled urls for same product for category ID 1 and 2 (Default category). Solved by changing value of that attribute directly in catalog_category_entity_int table in database.

I think that it is also is a category and product naming issue which it is not catched by the UrlRewrite handling in Magento 2 when the category property "Anchor" is set to "Yes".

I have tried a simple test on 2.1.3 like this:

  1. Create subcategory with name: "Top" and anchor: "Yes" under "Default Category"
  2. Create subcategory with name: "Test" and anchor: "Yes" under "Top"
  3. Create product with name: "Test" with assigning it to the category "Test"

On saving the product an exception occures in:
\Magento\UrlRewrite\Model\Storage\DbStorage::insertMultiple

I have added some var_dump to get the message (Magento 2 throws another exception instead of logging the message or forwarding the exception...).

Message:

SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry 'top/test.html-1' for key 'URL_REWRITE_REQUEST_PATH_STORE_ID', query was: INSERT INTO url_rewrite (redirect_type,is_autogenerated,metadata,description,entity_type,entity_id,request_path,target_path,store_id) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?), (?, ?, ?, ?, ?, ?, ?, ?, ?), (?, ?, ?, ?, ?, ?, ?, ?, ?)

Magento 2 can not insert this UrlRewrite "top/test.html" for the product "Test" because it is already present for the category "Test". If the property "Anchor" of the category "Top" is changed to "No", the product becomes saveable because no such UrlRewrite will be added for the product "Test". The same issue occures in deeper category level. The product UrlRewrites are not matched against the category UrlRewrites if the anchor category property is used.

Best thing in frontend: Magento 2 does only use the canonical urls for the products shown in the categories...

@janmyszkier you saved my friday!

@basselalaraaj what did you do to FIND those duplicates and in which table?

The issue I had was that there were products without names, which must have been allowed through on the import, which is probably bad.

When you have products without names, the url keys will be the same.

"" (empty) or ".html" or "/.html"

So delete any products without names.

Same as boxyman, here:
https://github.com/magento/magento2/issues/1471

Turned out that was the case for me as well. I imported a large number of products in bulk, which some of them somehow doesn't copy product name over and hence put an empty string on the URL.

After I fixed those products, I was able to do things with categories again without running into the URL key issue.

How are you guys finding products that have blank names? (is there an easy way to identify them via the product filter?) or a DB query to help identify them?

@spyrule Products > Catalog > sort by name

I had the same issue and, after troubleshooting, I found that a product was imported and that the url_rewrite table didn't convert the request_path value to lowercase. When the category, or product, was saved it ran into an integrity constraint violation and was unable to create the correct, converted to lowercase entry. After manually changing the value in the database everything worked just fine. You can use the query below to check for any uppercase values.

SELECT * FROM url_rewrite WHERE request_path REGEXP BINARY '[A-Z]';

Is this issue fixed with 2.1.4?

Magento 2.1.4 -problem is still not resolved.

I ran into this issue on a 2.1.4 Enterprise site where my client had imported products using the native importer and used uppercase url keys. I resolved this by changing all url keys to lowercase using the below query. Use this query at your own risk and only after extensive testing.

-- ##########################
-- Update Product Data
-- ##########################

-- For review purposes, find all products with uppercase url keys
SELECT * 
    FROM catalog_product_entity_varchar 
    WHERE
        `value` REGEXP BINARY '[A-Z]' 
        AND attribute_id = (SELECT attribute_id FROM eav_attribute WHERE `attribute_code` = 'url_key' AND `entity_type_id` = 4);


-- Update all product url keys that have uppercase values to make them have lowercase values
UPDATE catalog_product_entity_varchar 
    SET `value` = LOWER(`value`) 
    WHERE 
        attribute_id = (SELECT attribute_id FROM eav_attribute WHERE `attribute_code` = 'url_key' AND `entity_type_id` = 4) 
        AND `value` REGEXP BINARY '[A-Z]';


-- ##########################
-- Update url_rewrite Data
-- ##########################

-- For review purposes, find all product url_rewrite entries with uppercase url keys
SELECT * FROM url_rewrite WHERE `entity_type` = 'product' AND request_path REGEXP BINARY '[A-Z]';

-- Update all product url keys that have uppercase values to make them have lowercase values
UPDATE url_rewrite 
    SET `request_path` = LOWER(`request_path`) 
    WHERE 
        `entity_type` = 'product'
        AND `request_path` REGEXP BINARY '[A-Z]';

Hi guys, in my case I received a bucket load of this issue.

Steps to reproduce my findings:

  • I imported products from a Magento 1.9 store to 2.1.4
  • I exported the CSV, cleaned up some data and tried to import it back.
  • I get around 50-100 of these url_rewrite errors (Specified URL key already exists)
  • I go and change every one of the urls in the CSV manually, upload and its imported fine with all my changes (except attribute_set_code, working solution for that issue is available on request).
  • Now, to confirm, if I look at the product url_key in the backend on a product whose url_key I rewrote, "item-a" -> "item-a-1" for example.
  • Export the csv. Reupload the csv with no changes

Result:
Don't you know it, the new url_key "item-a-1" gets the (Specified URL key already exists) error again.

@quynhvv Thanks for the proposed solution. However, I tried your query, returns 0 rows.

When will this be finally fixed? issue is up since more than a year now?!

Agreed. Please prioritise this.

I have same issue when I change photo on my Category page. Already 5 months and version 2.1.4 now and we have a bug still unfixed.

This is probably one of the biggest bug in the code since it affects Imports, Category and Product management yet somehow the development team still haven't fixed this issue.

Not fixed in 2.1.5, sadly.

2.1.5 was a useless release, it just updated the license headers.

Magento team, please get this fixed.. many projects we are working on currently have this issue..

i had same error.... some of subcategories had same url key as some products... after i change all problematic url keys, categories can be saved....

it was magento 1.4.1 -> 1.9.3.2 -> 2.1.5

protected function doReplace($urls) {
    foreach ($this->createFilterDataBasedOnUrls($urls) as $type => $urlData) {
        $urlData[UrlRewrite::ENTITY_TYPE] = $type;
        $this->deleteByData($urlData);
    }
    $data = [];
    foreach ($urls as $url) {
        $data[] = $url->toArray();
    }

    //$sql = "SELECT * FROM url_rewrite";
    //$result = $this->connection->fetchAll($sql); 
    foreach($data as $k=>$newrow){
        if($newrow['request_path'] == ".html"){
            unset($data[$k]);
            continue;
        }
        if(strpos($newrow['request_path'],"/.") !== false){
            unset($data[$k]);
            continue;
        }
        /*foreach($result as $j=>$oldrow){
            if($newrow['request_path'] == $oldrow['request_path']){
                unset($data[$k]);
            }
            if($newrow['target_path'] == $oldrow['target_path']){
                unset($data[$k]);
            }
        }*/
    }
    $this->insertMultiple($data);
}

in vendor/magento/module-url-rewrite/Model/Storage/DbStorage.php this worked for me.
It was often assigning invalide request_path that just said .html and it was doing it for a product type despite it saving a category. I'm sure no one has a mysite.com/.html page so ... It was also doing things like request_path with product/.html which is obviously messed up and wrong. You can add other checks. I separated the if statements to make it easy to test each one. I used print_r statements because that was the most direct path to getting feedback on the code. So far it works for me. The commented stuff you can uncomment if you need it.

I am facing this issue in Magento 2.1.3 EE.
Mine is fixed by truncating the url rewrite table.

hello @sanjayjethva, thank you for the report, the internal ticket is created MAGETWO-66480.

@sanjayjethva Please fix this, we have this issue in production

I also hope Magento team can fix it ASAP.

So, I tried everything. The solution in my case, was the url_key of the products, not the categories. I exported all my products (about 10000) and I changed all the url_key of the products to numbers and letters, BUT, all LOWER case letters. Then I imported everything back again. I was able to save and modify categories again with no URL key error again. Hope this helps. Magento Ver. 2.1.2

Have been wresting with this issue on a production site for over half a year now. Many hours of pain and frustration because of this.

In my case I think it may be due to a mistmatch between entity_id and row_id causing the URL creation process to think that the URL key for a product is blank when it it's actually just not able to find the attribute value properly. This has caused issues in other places also. I've had to hack together a very ugly solution where I SQL update row_id to equal entity_id, collecting and updating any other tables that reference this column, changing their value to match. Ugh.

@joshdavenport Can you provide a few queries for people to test if they are experiencing the same problem?

@gustavogravina Can you confirm that if there are capitals in the URL keys this happens? I've just exported my product catalog to check and I've got a few. Also, some URL keys are empty.

Let me know because this issue has been bugging me for months now 😢

@TommyKolkman Yes, in my case, the Capital in the url_key was the problem. Also, empy url or empty names in products caused problems in my setup. Good luck

@TommyKolkman @gustavogravina Is there any queries that anybody know to check for capital letters and/or blank URLs for both products and categories?

@spyrule You can reference the query I posted above for how to do this for product urls and you can then tweak it for category urls.

In addition to the uppercase product urls, here are some other reasons I've found for why saving a category could result in a "URL key for specified store already exists" error:

1 - Product urls with uppercase url_key values

As many have already mentioned in this thread, products with uppercase url keys can cause this error. See my previous comment for queries on how to address this. It sounds like categories with uppercase url keys might also cause this issue.

2 - Product urls with duplicate keys

When a category is saved, the url_rewrite table is refreshed with products in that category.

My client imported their products via CSVs and had some products with url_key values that were causing conflicts when the url_rewrite table was being refreshed. For example, they had products with SKUs like:

  1. CCP-MP24A1-XC-RW:500FT
  2. CCP-MP24A1 XC RW:500FT
  3. CCP.1234
  4. CCP-1234
  5. CCP-DWR-RR40
  6. CCP- DWR-RR40

When Magento tried to insert the urls for the above products into the url_rewrite table, it ran into issues because Magento made the following replacements with the SKUs above:

  • Replaced spaces with dashes (so SKU #2 above conflicted with sku #1)
  • Replaced periods with dashes (so SKU #4 above conflicted with sku #3)
  • Replaced "- " with "-" (a dash with a space after it got replaced with a dash) (so SKU #6 above conflicted with sku #5)

To find products with conflicting url keys, I ran this query (IMPORTANT: If you're using Community instead of Enterprise, replace the instance of row_id value with entity_id):

SELECT 
    group_concat(catalog_product_entity_varchar.value SEPARATOR "\n") AS url_keys,
    group_concat(catalog_product_entity_varchar.row_id) AS product_ids
FROM catalog_product_entity_varchar
WHERE attribute_id = 124 -- attribute ID for url_key attribute
-- MySQL doesn't have regex replace, so nesting replace functions to replace spaces and periods with dashes and replacing "- " with "-"
GROUP BY REPLACE(REPLACE(REPLACE(`value`, '- ', '-'), ' ', '-'), '.', '-')
HAVING 
    count(value_id) > 1
    AND count(DISTINCT row_id) > 1;

My client then manually fixed the products with conflicting url keys and that fixed this issue.

3 - Products with empty name/url key attributes

This issue is less likely to be encountered on typical projects, but my merchant had somehow imported a couple of products with empty name and url keys. This caused an error like this when saving a category:

URL key for specified store already exists. - SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '1' for key 'URL_REWRITE_REQUEST_PATH_STORE_ID', query was: INSERT INTO `url_rewrite` (`redirect_type`,`is_autogenerated`,`metadata`,`description`,`store_id`,`entity_type`,`entity_id`,`request_path`,`target_path`) VALUES…

I ran this query to find products with missing url_key attribute values, and once those products were resolved, the category was able to be saved:

SELECT * FROM `url_rewrite` WHERE `request_path` LIKE '';

4 - Very deep category tree

In some cases, a very deep category tree can cause this issue. At some point in the rewrite construction process, product urls are stored in a varchar 255 field. If you have product urls that include all the categories above them, you end up with long urls. Truncated to 255, they seem like duplicate urls. Take this example using 10 as a limit instead of 255:

cata/catb/catc/some-product
cata/catb/some-other-product
cata/catb/catc/another-product

These will all get truncated to cata/catb/, causing a duplicate url error. I believe the resolution to this was to change "STORES > Configuration > CATALOG > Catalog > Search Engine Optimization > Use Categories Path for Product URLs" to "No" (which is the default Magento setting).

@erikhansen I tried running the :

SELECT 
    group_concat(catalog_product_entity_varchar.value SEPARATOR "\n") AS url_keys,
    group_concat(catalog_product_entity_varchar.row_id) AS product_ids
FROM catalog_product_entity_varchar
WHERE attribute_id = 124 -- attribute ID for url_key attribute
-- MySQL doesn't have regex replace, so nesting replace functions to replace spaces and periods with dashes and replacing "- " with "-"
GROUP BY REPLACE(REPLACE(REPLACE(`value`, '- ', '-'), ' ', '-'), '.', '-')
HAVING 
    count(value_id) > 1
    AND count(DISTINCT row_id) > 1;

However in CE it generates an error:

1054 - Unknown column 'catalog_product_entity_varchar.row_id' in 'field list'

@spyrule My bad. The MySQL query I posted was for Magento Enterprise. I edited my comment above with this:

If you're using Community instead of Enterprise, replace the instance of row_id value with entity_id

perfect, thank you!

I'm having this same issue on magento 2.1.4

+1 pretty major issue here, on 2.1.5

+1 please asap

same issue on 2.1.5, I also have a support ticket open for this.

Same issue, how to solve this on 2.1.5?

@winds1983 you need to read ^^^, there are several possible causes and each have separate solutions. Some are not yet resolved.

I'm on Magento 2.1.5. My client just bulk imported about 2000 products via csv and now I can no longer save categories that have products associated to them. This is a very real and very severe issue. Do something about this @magento-team.

I'm working on this issue.

same issue with WEBAPI Soap and manually saving a category in 2.1.5

This Magento 2 bug you can directy fix is changing file

File Path :vendor/magento/module-url-rewrite/Model/Storage/DbStorage.php

Orginal Code:

from

protected function doReplace($urls)
{
    foreach ($this->createFilterDataBasedOnUrls($urls) as $type => $urlData) {
        $urlData[UrlRewrite::ENTITY_TYPE] = $type;
        $this->deleteByData($urlData);
    }
    $data = [];
    foreach ($urls as $url) {
        $data[] = $url->toArray();
    }
    $this->insertMultiple($data);
}

into

protected function doReplace($urls)
{
    foreach ($this->createFilterDataBasedOnUrls($urls) as $type => $urlData) {
        $urlData[UrlRewrite::ENTITY_TYPE] = $type;
        $this->deleteByData($urlData);
    }
    $data = [];
    foreach ($urls as $url) {
        $data[] = $url->toArray();
    }

     /* Add this line : Get rid of rewrite for root Magento category to unduplicate things
    foreach($data as $key =>$info){
            if(isset($info['target_path']) && stristr($info['target_path'],'/category/1') && $info['entity_type']=='product'){
                    unset($data[$key]);
            }
    }

    $this->insertMultiple($data);
}

After insert this line clear cache.

@sadeeshmca Unfortunately, your code for the "doReplace" method doesn't work for me.
I do a full product import and still receive the dreaded error.

@atultechelogy Any updates on this? This is a critical bug and causing no end of contention with my client.

Since this is only a minor problem, take your time to fix this, no need to hurry :)

For me the issue came from long url_keys building up to create over 255 chars request_path. When it was looking up on url_rewrite table with the full path (over 255 chars) mysql was returning no hits and magento was trying to create a 301 but caused a dup key as the original was already maxed at 255.

All I did, and confirmed it works, was to create a preference overriding the Magento\CatalogUrlRewrite\Model\ProductUrlPathGenerator::getUrlPath to:

class ProductUrlPathGenerator extends \Magento\CatalogUrlRewrite\Model\ProductUrlPathGenerator
{
    /** @inheritdoc */
    public function getUrlPath($product, $category = null)
    {
        $path = $product->getData('url_path');
        if ($path === null) {
            $path = $product->getUrlKey()
                ? $this->prepareProductUrlKey($product)
                : $this->prepareProductDefaultUrlKey($product);
        }

        $path = $category === null
            ? $path
            : $this->categoryUrlPathGenerator->getUrlPath($category) . '/' . $path;

        return substr($path, 0, 255);
    }
}

This way, internally it matches the db field length and it doesn't try to create a new 301 when not needed.

(this it is awfully slow process and it is weird that it even re-calcs the urls when changing the name of a cat as mentioned here #9706 )

having the same issue in 2.1.4. played with my database a little and what worked for me was going to catalog_category_entity_varchar and searched for the entity_id in question and deleted just the url key attribute in my case attribute_id 33 went back to the admin filed out the url key with the exact same key as was deleted. can now make changes and save that category.

Before editing the Magento core file Magento\UrlRewrite\Model\Storage\DbStorage, you can log in this class the $data param of the function insertMultiple(), and check what value has $data['request_path'] before raising the exception.
It may give you a clue of what URL is duplicated.

I am on 2.1.6 and thanks to @erikhansen comment "Product URLs with duplicate key" I could solve it. It was indeed a duplicate URL key - so the error totally makes sense; you're also not allowed to have duplicate SKUs.

Not a real Magento issue to me - just the error message could be clearer what the duplicate URL key is.

From what I can gather Magento does a batch insert with multiple values/rows so it could be any of them. I modified the exception catch to further try to insert one by one and report the offending record. Proved helpful for me to identify the cause on a large db.

On 9 Jun 2017, at 20:39, codedge notifications@github.com wrote:

I am on 2.1.6 and thanks to @erikhansen comment "Product URLs with duplicate key" I could solve it. It was indeed a duplicate URL key - so the error totally makes sense; you're also not allowed to have duplicate SKUs.

Not a real Magento issue to me - just the error message could be clearer what the duplicate URL key is.

—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub, or mute the thread.

Another thing that I've found helpful when troubleshooting this error is editing the "URL key for specified store already exists." error message to include a section of the problematic MySQL query. See this Gist for a patch that you can apply to your development/stage environment.

So far my only remaining errors on this are to do with categories, and thats purely because the compiled length is greater than 256 characters. I'm not sure if thats been fixed in 2.1.6, but I'm still at 2.1.3.

@spyrule - Per item 4 in my comment from April 1:

I believe the resolution to this was to change "STORES > Configuration > CATALOG > Catalog > Search Engine Optimization > Use Categories Path for Product URLs" to "No" (which is the default Magento setting).

Obviously this is a workaround to the core issue, but it should solve your issue.

0
down vote

I was also facing same issue while adding/editing categories.

Firstly I found there was wrong attribute id in "catalog_category_entity_varchar" table for url_key and url_path. Then I checked the exect attribute_id of both attributes ('url_key' and 'url_path').

e.g in "catalog_category_entity_varchar" table it was showing '117' and '118' but exact id was '119' and '120'. Then I found there was some rows in "catalog_category_entity_varchar" table with these (correct id '119','120').

I followed below steps to resolve issue.

firstly I searched rows in "catalog_category_entity_varchar" where attribute id is in (117,118) and exported the data from table.
then I searched rows in "catalog_category_entity_varchar" where attribute id is in (117,118,119,120) and deleted these data (rows) from table.
then I just opened exported file in notpadd++ then I changed attribute ids 117 with 119 and 119 with 120 and import the data again.

Make sure take the backup of the database before doing above steps.

Have same issue. None of proposed solution works for my case. The other problem is that category has a lot of products. I've tryed replace insertMultiple call with insertOnDuplicate but got another error:

[2017-07-05 14:18:08] main.CRITICAL: Exception: Notice: Undefined index: category_id in magento/module-catalog-url-rewrite/Model/Category/Plugin/Storage.php on line 49 in magento/framework/App/ErrorHandler.php:61

adding check for index existence helps and now category saves ok.

Internal ticket for ver. 2.1 - MAGETWO-66481

FINALLY!!!

@cpartica @buskamuza can you backport fix for this issue to 2.1.x branch also?

@Koc , there is an internal ticket for it as mentioned above. Unfortunately, I can't say anything about time line as it should be prioritized.

@cpartica Can you provide a patch for 2.1.x ? Or backport it into 2.1.8 ?

Hi guys,

Let's try my solutions issue #7298.

Hope this help.
Thanks.

@cpartica I would also like to see a patch that we can apply to 2.1.x. This issue is causing no end of grief for my client's ecommerce site.

agreed, please guys, sort this out. SEO nightmare

On Sun, Jul 23, 2017 at 10:12 PM, Christopher Staley <
[email protected]> wrote:

@cpartica https://github.com/cpartica I would also like to see a patch
that we can apply to 2.1.x. This issue is causing no end of grief for my
client's ecommerce site.

—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
https://github.com/magento/magento2/issues/6671#issuecomment-317275173,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AV1NbbFcEZKrWTmHuPY675qUQhLI9iw6ks5sQ5sygaJpZM4KBPCb
.

Has anyone figured out how to apply MAGETWO-66480 to 2.1.7?

@dverkade I notice you have a pull request to fix this here:
https://github.com/magento/magento2/pull/10356

Is that applicable to v2.1.x?

Hey @christopher-s,

We have created the changes as core fixes for ourselfs and then reworked those to create the PR. There is some difference in the way the URL rewrites are handled between Magento 2.1 and 2.2 so the code is a bit different, but you can look at my changes in the PR and create a solution for Magento 2.1 from it if you like. Please upvote / like the PR, because there is quite a discussion going on and I think the more people agree with the changes and get involved with the discussion will convince the core team to look at this more seriously.

@dverkade the fix is included in the latest version (2.1.9)?

Its not posted as a fix in 2.1.9 KB, and it just failed G1 testing by the engineering team. So I'd say no.

@sanjayjethva, thank you for your report.
The issue is already fixed in 2.2.0

Was this page helpful?
0 / 5 - 0 ratings