I have been getting errors similar to the following:
Uncaught PHP Exception Drupal\\Core\\Entity\\EntityStorageException: "SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '1zvDyLS_nqAUEDQSKpZXidjJJeLUMXrvAdoCL6x9qRw' for key 'hash': INSERT INTO {redirect} (type, uuid, language, hash, uid, redirect_source__path, redirect_source__query, redirect_redirect__uri, redirect_redirect__title, redirect_redirect__options, status_code, created) VALUES (:db_insert_placeholder_0, :db_insert_placeholder_1, :db_insert_placeholder_2, :db_insert_placeholder_3, :db_insert_placeholder_4, :db_insert_placeholder_5, :db_insert_placeholder_6, :db_insert_placeholder_7, :db_insert_placeholder_8, :db_insert_placeholder_9, :db_insert_placeholder_10, :db_insert_placeholder_11); Array\n(\n [:db_insert_placeholder_0] => redirect\n [:db_insert_placeholder_1] => 76b514b2-a1a1-4332-8920-dc107b4d3b9e\n [:db_insert_placeholder_2] => en\n [:db_insert_placeholder_3] => 1zvDyLS_nqAUEDQSKpZXidjJJeLUMXrvAdoCL6x9qRw\n [:db_insert_placeholder_4] => 1\n [:db_insert_placeholder_5] => about/staff/guarini-joe\n [:db_insert_placeholder_6] => a:0:{}\n [:db_insert_placeholder_7] => internal:/node/48\n [:db_insert_placeholder_8] => \n [:db_insert_placeholder_9] => a:0:{}\n [:db_insert_placeholder_10] => 301\n [:db_insert_placeholder_11] => 1497982330\n)\n" at /var/www/html/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php line 777, referer: http://webroot/node/48/edit
This error occurs when I try to edit and save a custom content node created by a different user (even though I am the admin user). Strangely, the error doesn't happen consistently as I'm able to successfully edit and save a few random records. The other user also reports that she is getting the same error when trying to edit one of her own records. Clearing Drupal cache did not remedy the situation.
Comments
Comment #2
timmillwoodThis looks like it might be a redirect module issue?
Comment #3
rvanderh1 commentedYes, I think you're correct about that. I will re-submit this as an issue in the Redirect module. Thanks.
Comment #4
timmillwoodWe can just move this straight to Redirect.
Comment #5
timmillwoodI guess it affects the D8 branch?
Comment #6
rvanderh1 commentedYes, I'm using Drupal 8.3.3 and Redirect 8.x-1.0-alpha5.
Comment #7
berdirWill need steps to reproduce, looks like somehow you manage to create redirects with the same hash?
holder_5] => about/staff/guarini-joe\n [:db_insert_placeholder_6] => a:0:{}\n [:db_insert_placeholder_7] => internal:/node/48\n [
this is the from => to redirect it is trying to create. are you changing the name of those staff entries? Can you check your redirect table for the record with hash 1zvDyLS_nqAUEDQSKpZXidjJJeLUMXrvAdoCL6x9qRw and post that here? Is it the same path as above or different?
Comment #8
rvanderh1 commentedI've pulled up the record from the redirect table. I should note that when I opened that record to edit, and saved without making any changes I didn't receive the error message. As I noted in my original posting, the error wasn't happening consistently nor was it happening on just this one record.
What specific info do you need from the data table?
Comment #9
nplowman commentedI was encountering the same issue.
Here's what I was able to track down:
When you update a node, redirect_path_update() is called to generate the redirect.
This function will attempt to call RedirectRepository->findMatchingRedirect() to check for an existing redirect first.
However, leading slashes are removed from the source path when a new redirect is created.
Example:
This was NOT being done when calling findMatchingRedirect(), which was causing the hashes to not match and thus allowing a some cases to slip through and throw the duplicate entry errors.
I'm attaching a patch with a fix.
Comment #10
nikunjkotechaPatch works perfectly fine.
Steps to reproduce (for my case)
* Taxonomy terms are created through drush command (through external API)
* When the title/name for the term was changed, it was creating redirects
* When the same changed for second time, it started giving error
* Additional note: it may be related to multi-lingual system too
Comment #11
nikunjkotechaChanging to needs review for patch to be checked through automated tests.
Comment #12
nikunjkotechaTest passed, updating to RTBC
Comment #13
berdirThe existing tests passed, yes, but we need to have a test that exposes this bug or some future refactoring might re-introduce this.
Comment #14
achapI just ran into the issue while trying to import some redirects from a D7 site through drush migration. It's because a redirect already exists in the database with the same hash.
The header of the generateHash method says that a hash is created based off the source_path, source_query and language:
I checked in the database and there was already a record with the same source_path, source_query and language as the redirect my migration was trying to import. So it's probably a good thing this error is thrown in this case, because you may not want your existing queries overwritten.
Any patch and test would need to take that into account.
Comment #15
achapThe patch in #9 doesn't fix it for me. I still get the following message:
SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry 'BSyomGAjF_qtCPwYv-eQ0bATX2_7Sxet7BsrITTz7y0' for key 'hash'
Comment #16
nikunjkotecha@achap possible to share the steps/scenario for your case?
Comment #17
achap@nikunjkotecha
Sure. I am running a migration that imports redirects from a D7 export csv to D8 redirect table. 98% of them import fine but my D8 site already has some existing redirects in it before the migration occurred. The hash is generated from source_path, source_query and language, so if any of my redirect imports have the same source_path, source_query and language as a redirect had when it was originally created via the UI the integrity constraint violation will occur.
Interestingly, some of the existing redirects have the same hash as the migrated redirects even though the source_path is different in the D8 database, which suggests that the D8 redirects had their source paths updated after the hash was created and a new hash was not created.
Comment #18
damondt commentedPatch works for me, thanks!
Comment #19
Anonymous (not verified) commentedPatch works here as well.
Comment #20
aswathyajish commentedThis patch (#9) is not working for me. Anybody please help.
Comment #21
achapSo I actually experienced the issue in the same way as the other posters and the patch in #9 works fine. Thanks for that. I added a simple Kernel Test that will expose this bug.
I think my issue in #14 might be because of my own migration code. In any case I don't think it should block this patch.
Comment #22
achapComment #23
rodrigoaguileraJust to be sure the test exposes the bug let's run only the test against the current code base
Comment #25
rodrigoaguileraPerfect.
I think #21 can be commited
Comment #26
berdirThanks. Leading / or not is unfortunately a mess, I think this change makes sense and ensures it is consistent.
Minor comments on the test, then this can be committed.
This is not a valid docblock description, should be a sentence describing what it does.
Referencing the d.o issue is not needed, that will be visible through the commit message/git blame.
I'd prefer to split this to two lines, one that calls fingMatchingRedirect() on a single line and stores it into a variable and then the assert.
Comment #27
achapHere you go. How's that?
Comment #28
achapComment #29
berdirThat was fast!
I did a bit of cleanup, new array syntax and simplified the test code quite a bit. I assume the large arrays were copied from what hook_path_update() receives which I guess made sense to you but I actually found quite confusing to understand.
If I just hardcode the data then the is much shorter and IMHO easier to understand, any objections?
PS: don't forget to provide an interdiff, which makes it easier for reviewers to see what changed. Trivial with git, either commit the original patch and diff against different commits or just apply to head (e.g. with git apply -3) then it is the git diff HEAD is the full patch and git diff is the changes/interdiff.
Comment #30
achapYes I copied from hook_update_path. That looks much better now, no objections from me!
Comment #32
berdirGreat, committed. Will do a new release soon.
Comment #34
vidorado commentedSorry for re-opening this issue. I was having this problem again with redirect 1.4
I realized that the redirect_path_update() hook wasn't deleting the redirect in database with the hash the new redirect will have. I don't know if this is the correct solution, i'm a little lost with the logic. I don't know why the redirect in database has the hash generated from the "node/xxx" string instead of the path alias string... but this was happening to me.
I can provide a dump of the $path variable at line 106:
An evaluation of "Redirect::generateHash("node/19251",[],"es")":
uiw673iLnkADyupNDaMwl7O2Rd08ej_dqkD3lTDCSp4
And the row at the database:
hash: uiw673iLnkADyupNDaMwl7O2Rd08ej_dqkD3lTDCSp4
redirect_source__path: apoyo/apoyo-empresarial/empresas-participantes/samsung-2
redirect_redirect__uri: internal:/node/19251
I also provide a patch to manually generate the hash from $path['source'] and deleting by hash from the database
Hope that helps, and that someone could get to a better solution or at least an understanding of the problem.
Comment #35
RAWDESK commentedExperienced a similar issue with updating/inserting redirects in Drupal 7.
Attached patch prevents this from happening in following use case :
- Pathauto is configured to only allow 1 alias (rest is diverted to be managed in redirects)
- Historical redirects (originating from a batch URL alias to redirect migration) are reused via node/edit UI or remote services layer
- these redirects are by implementation first disabled within redirects (update status to 0)
- this update fails because of clashing hash primary key existance
It might help someone experiencing the same.
Comment #36
dshields commentedHere's an updated version of #34