SonarSource/sonarqube · error · java.lang.IllegalArgumentException

This builder should not be used with primary keys

Error message

This builder should not be used with primary keys

What it means

DropConstraintBuilder intentionally refuses constraint names starting with 'pk_'. Primary keys are handled by a dedicated finder/dropper because their SQL differs (sometimes requiring sequence handling on PostgreSQL), so using this builder for a PK would produce wrong statements.

Source

Thrown at server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/sql/DropConstraintBuilder.java:55

 */
public class DropConstraintBuilder {

  private final Dialect dialect;
  private String tableName;
  private String constraintName;

  public DropConstraintBuilder(Dialect dialect) {
    this.dialect = dialect;
  }

  public DropConstraintBuilder setTable(String s) {
    this.tableName = s;
    return this;
  }

  public DropConstraintBuilder setName(String s) {
    if (s.startsWith("pk_")) {
      throw new IllegalArgumentException("This builder should not be used with primary keys");
    }
    this.constraintName = s;
    return this;
  }

  public List<String> build() {
    validateTableName(tableName);
    validateIndexName(constraintName);
    return singletonList(createSqlStatement());
  }

  private String createSqlStatement() {
    return switch (dialect.getId()) {
      case MsSql.ID, Oracle.ID, PostgreSql.ID, H2.ID -> "ALTER TABLE " + tableName + " DROP CONSTRAINT " + constraintName;
      default -> throw new IllegalStateException("Unsupported dialect for drop of constraint: " + dialect);
    };
  }
}

View on GitHub (pinned to 184c821202)

Solutions

  1. Use the primary-key specific removal path (DbPrimaryKeyConstraintFinder + dedicated PK drop) instead of DropConstraintBuilder for 'pk_' constraints.
  2. Only pass non-primary-key constraint names to setName().
  3. Normalize name casing so real PK names aren't missed if your DB stores them uppercase.

Example fix

// before
new DropConstraintBuilder(dialect, "issues").setName("pk_issues")...
// after
String pk = constraintFinder.constraintQuery("issues"); // use PK-specific handling
new DropConstraintBuilder(dialect, "issues").setName("fk_issues_user")...
Defensive patterns

Strategy: validation

Validate before calling

if (constraintName.toLowerCase().startsWith("pk_")) { usePrimaryKeyRemovalPath(table); } else { new DropConstraintBuilder(dialect, table).setName(constraintName); }

Type guard

boolean isPrimaryKeyConstraint(String name) { return name != null && name.toLowerCase().startsWith("pk_"); }

Prevention

When it happens

Trigger: Calling setName("pk_issues") or any name starting with lowercase 'pk_' before build().

Common situations: Migration author loops over all constraints of a table and tries to drop PKs with the generic builder; copy-pasted constraint name; case confusion since only lowercase 'pk_' prefix is rejected.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of SonarSource/sonarqube@184c821202 (2026-09-09). Data as JSON: /api/errors/a45e8136822739f5. Report an issue: GitHub.