hibernate/hibernate-orm · error · IllegalStateException

Same column is added more than once with different values fo

Error message

Same column is added more than once with different values for isUpdatable

What it means

The same column was re-added with conflicting updatable flags: justAddColumn() found the column already present but with a different updatable value, meaning two mappings of one column disagree on whether it participates in UPDATE statements. It is the updatability sibling of the insertable check and throws IllegalStateException for the same reason: contradictory write behavior on a single column.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/mapping/SimpleValue.java:229

	}

	protected void justAddColumn(Column column) {
		justAddColumn( column, true, true );
	}

	protected void justAddColumn(Column column, boolean insertable, boolean updatable) {
		final int index = columns.indexOf( column );
		if ( index == -1 ) {
			columns.add( column );
			insertability.add( insertable );
			updatability.add( updatable );
		}
		else {
			if ( insertability.get( index ) != insertable ) {
				throw new IllegalStateException( "Same column is added more than once with different values for isInsertable" );
			}
			if ( updatability.get( index ) != updatable ) {
				throw new IllegalStateException( "Same column is added more than once with different values for isUpdatable" );
			}
		}
	}

	protected void justAddFormula(Formula formula) {
		columns.add( formula );
		insertability.add( false );
		updatability.add( false );
	}

	public void sortColumns(int[] originalOrder) {
		if ( columns.size() > 1 ) {
			final var originalColumns = columns.toArray( new Selectable[0] );
			final var originalInsertability = toBooleanArray( insertability );
			final var originalUpdatability = toBooleanArray( updatability );
			for ( int i = 0; i < originalOrder.length; i++ ) {
				final int originalIndex = originalOrder[i];
				final var selectable = originalColumns[i];

View on GitHub (pinned to fad1729dce)

Solutions

  1. Make updatable (and insertable) identical everywhere the column is mapped, usually by marking the redundant side insertable=false and updatable=false
  2. Or remove one of the two mappings of the column
  3. For FK+id pairs, keep the association writable and the id column read-only

Example fix

// before
@Column(name = "user_id")
private Long userId; // insertable=true, updatable=true
@ManyToOne @JoinColumn(name = "user_id", updatable = false)
private User user;  // updatable=false -> mismatch

// after
@Column(name = "user_id", insertable = false, updatable = false)
private Long userId;
@ManyToOne @JoinColumn(name = "user_id")
private User user;
Defensive patterns

Strategy: validation

Validate before calling

static void checkConsistentColumnFlags(Class<?> entity) {
    Map<String, String> byColumn = new HashMap<>();
    for (Field f : entity.getDeclaredFields()) {
        JoinColumn jc = f.getAnnotation(JoinColumn.class);
        Column col = f.getAnnotation(Column.class);
        if (jc == null && col == null) continue;
        String name = jc != null ? jc.name() : (!col.name().isEmpty() ? col.name() : f.getName());
        boolean ins = jc != null ? jc.insertable() : col.insertable();
        boolean upd = jc != null ? jc.updatable() : col.updatable();
        String sig = ins + "/" + upd;
        String prev = byColumn.put(name, sig);
        if (prev != null && !prev.equals(sig)) {
            throw new IllegalStateException(entity.getName() + '.' + f.getName() + " -> " + name);
        }
    }
}

Try / catch

try { metadata.buildSessionFactory(); }
catch (IllegalStateException e) {
    if (e.getMessage().contains("isUpdatable")) {
        // find both mappings of the column and make updatable agree
    }
    throw e;
}

Prevention

When it happens

Trigger: @JoinColumn(name=..., updatable=false) on one side and a default-updatable @Column with the same name on the other; a read-only association layered over a writable basic column; overrides reintroducing the column with updatable changed.

Common situations: Read-only mirror columns for foreign keys; immutable audit columns mapped twice; embeddable overrides with mismatched flags.

Related errors


AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22). Data as JSON: /api/errors/70760d3fdae0c31f. Report an issue: GitHub.