Repository navigation
[CASE-4454] Unique violation without key detail is handled on PostgreSQL - #82
Merged
Merged
Conversation
PostgreSQL leaves the `DETAIL: Key (...)=(...) already exists.` line out of a unique violation on a table the current role is subject to row-level security on. `PostgresqlAdapter.unique_error_columns` called `split` on the nil match, so `validates_db_uniqueness_of` raised NoMethodError instead of adding the error. Validators are also registered under the index name, which the error still carries, so returning nil (as the MySQL adapter already does) is enough. Co-authored-by: Claude <noreply@anthropic.com>
AlfonsoUceda
approved these changes
Oct 22, 2026
…s it The reason `unique_error_columns` can return nil was written twice, once in each spec, and not on the method. Keep one explanation there and shorten the specs to point at it.
This was referenced Oct 27, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Ticket: CASE-4454
Problem
On PostgreSQL, a unique violation on a table that the current role is subject to row-level security on carries no
DETAIL: Key (...)=(...) already exists.line. PostgreSQL omits it because the values could belong to a row the role cannot see.PostgresqlAdapter.unique_error_columnsdoeserror.message[/Key \((.+)\)=/, 1].split(', '), so the missing line makes it callsplitonnil.validates_db_uniqueness_ofthen raisesNoMethodError: undefined method 'split' for nilwhere it should add the validation error. It only happens on the path this gem exists for: two writers pass validation and the index decides.Fix
Rescuerbuilds two keys for a unique violation, one from the columns and one from the index name, andUniquenessKeyExtractor.attribute_by_keyregisters every validator under both. The index name is still in the message (duplicate key value violates unique constraint "..."), so returningnilis enough. The MySQL adapter already returnsnilfromunique_error_columnsand relies on the same thing.Tests
spec/validations/validates_db_uniqueness_of_row_level_security_spec.rb: a table with row-level security enabled, run as a role that is not a superuser (a superuser bypasses RLS and keeps the detail line). It covers an attribute-only validator, a scoped validator and anindex_name:validator, each throughcreateandcreate!. A first example asserts the error really has noKey (line, so it fails if PostgreSQL changes.spec/adapters/postgresql_unique_error_columns_spec.rb: the adapter method with and without the detail line.Without the change, 7 of the 9 new examples fail with
undefined method 'split' for nil; with it all 9 pass. The existing PostgreSQL examples still pass (166 invalidates_db_uniqueness_of_spec.rb, 25 in the presence and belongs-to specs), and RuboCop is clean with the repo config.The new RLS spec creates and drops a role, so it needs a database user that can create roles (CI's
rootcan). It skips otherwise.Not run
MySQL and SQLite: the gems were not available where I ran this. The change touches only the PostgreSQL adapter.
Found while testing PostgreSQL row-level security on
toptal/career-services-backend, where 7 specs hit this.🤖 Generated with Claude Code