5

I'm getting the error, "URL key for specified store already exists" when I try moving or adding products to a category in Magento 2 (Version 2.1). I have searched all over for a fix and even tried the fix here on Gihub but still I keep getting the error. The other problem even is that when I manually add or change a "URL Key" to make it work I still get the error.

Any help would be much appreciated.

2 Answers 2

7

We had a similar issue where we couldn't save categories and after much database searching and debugging I found the issue was when it updated the product url's for the category. We'd imported and deleted products previously but found out they still had entries in the url_rewrite table. So the request_path already existed.

To clear it out I had to run the query

delete from url_rewrite where entity_type='product' and entity_id NOT IN (Select entity_id from catalog_product_entity);

To check if you do have ghost records you can run

select count(*) from url_rewrite where entity_type='product' and entity_id NOT IN (Select entity_id from catalog_product_entity);

Good luck

3
  • Thank so much @JasonWatt for the help! When I ran both commands I got the error, "#1146 - Table 'magnetodatabase.url_rewrite' doesn't exist". So I thought maybe I don't have a "url_rewrite" table. But when I checked with "select "url_rewrite" command the "url_rewrite" table came up.
    – P. Paul
    Aug 26, 2016 at 17:42
  • Hi Paul Not sure where you're running the sql from but if it's on the command line try running use magnetodatabase first before the queries. Always test with the select query I sent first.
    – Jason Watt
    Aug 29, 2016 at 23:40
  • Thanks for the help. I surely did run it later with the prefix and the queries worked. But the other problem was is that the first query didn't didn't delete anything according to the message. Then I used the second one to check for the ghost records and that one also stated no record found. In effect, the problem still exists. Thanks!
    – P. Paul
    Aug 31, 2016 at 0:40
0

I have fixed this issue in more than 3-4 projects.

If you want to resolve this issue, you can upgrade your version with latest one or try below code logic:

Try this solution by overriding below function in your custom module :)

Path: vendor/magento/module-url-rewrite/Model/Storage

protected function doReplace(array $urls){ 
    $this->deleteOldUrls($urls); 
    $data = [];
    $storeId_requestPaths = [];
    foreach ($urls as $url) {
        $storeId = $url->getStoreId();
        $requestPath = $url->getRequestPath();
        $sql = "SELECT * FROM url_rewrite where store_id = $storeId and request_path = '$requestPath'";
        $exists = $this->connection->fetchOne($sql); 
        if ($exists) continue;
        $storeId_requestPaths[] = $storeId . '-' . $requestPath;
        $data[] = $url->toArray();
    }

    // Remove duplication data;
    $n = count($storeId_requestPaths);
    for ($i = 0; $i < $n - 1; $i++) {
        for ($j = $i + 1; $j < $n; $j++) {
            if ($storeId_requestPaths[$i] == $storeId_requestPaths[$j]) {
                unset($data[$j]);
            }
        }
    }
    try {
        $this->insertMultiple($data);
    } catch (\Magento\Framework\Exception\AlreadyExistsException $e) {
        /** @var \Magento\UrlRewrite\Service\V1\Data\UrlRewrite[] $urlConflicted */
        $urlConflicted = [];
        foreach ($urls as $url) {
            $urlFound = $this->doFindOneByData(
                [
                    UrlRewriteData::REQUEST_PATH => $url->getRequestPath(),
                    UrlRewriteData::STORE_ID => $url->getStoreId(),
                ]
            );
            if (isset($urlFound[UrlRewriteData::URL_REWRITE_ID])) {
                $urlConflicted[$urlFound[UrlRewriteData::URL_REWRITE_ID]] = $url->toArray();
            }
        }
        if ($urlConflicted) {
            throw new \Magento\UrlRewrite\Model\Exception\UrlAlreadyExistsException(
                __('URL key for specified store already exists.'),
                $e,
                $e->getCode(),
                $urlConflicted
            );
        } else {
            throw $e->getPrevious() ?: $e;
        }
    }

    return $urls;
}

Happy Coding :)

Thanks,

Ketan T.

Your Answer

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

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