#7169·dbal

Partial indexes with same columns but different WHERE clause conflict when index name is omitted

Author: BadrutdinCreated Sep 29, 2025Updated Jun 25, 2026

Partial indexes with same columns but different WHERE clause conflict when index name is omitted

When using PostgreSQL partial indexes on the same columns but with different WHERE clauses, Doctrine DBAL generates the same automatic index name for all of them. This leads to a conflict during schema diff/migration, unless a custom name is provided manually for each index. Example:

php
#[ORM\Index(
    columns: ['user_id', 'id'],
    options: ['where' => '(removed_at IS NULL)']
)]
#[ORM\Index(
    columns: ['user_id', 'id'],
    options: ['where' => '((removed_at IS NULL) AND (unsubscribed_at IS NOT NULL))']
)]
#[ORM\Index(
    columns: ['user_id', 'id'],
    options: ['where' => '((removed_at IS NULL) AND (unsubscribed_at IS NULL))']
)]

All three indexes above generate the same automatic name, because \Doctrine\DBAL\Schema\AbstractAsset::_generateIdentifierName only considers the column list, not the where condition. As a result, running doctrine:migrations:diff produces an error like: An index with name "idx_4c62e638a76ed395bf396750" was already defined on table "contact".