hibernate/hibernate-orm · error · MappingException

Expecting column for collection id (idbag), but found formul

Error message

Expecting column for collection id (idbag), but found formula [%s.%s]

What it means

An <idbag> collection derives row identity from <collection-id>, and that id must map to a physical column. PluralAttributeSourceIdBagImpl builds the relational value source for the collection id and requires a ColumnSource; a formula resolves to a DerivedValueSource instead, so bootstrap fails with this message naming the containing attribute role and the idbag name.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/boot/model/source/internal/hbm/PluralAttributeSourceIdBagImpl.java:75

					@Override
					public SizeSource getSizeSource() {
						return Helper.interpretSizeSource(
								idBagMapping.getCollectionId().getLength(),
								(Integer) null,
								null
						);
					}

					@Override
					public List<JaxbHbmColumnType> getColumnOrFormulaElements() {
						return idBagMapping.getCollectionId().getColumn();
					}
				}
		);

		if ( !(collectionIdRelationalValueSource instanceof ColumnSource) ) {
			throw new MappingException(
					String.format(
							Locale.ENGLISH,
							"Expecting column for collection id (idbag), but found formula [%s.%s]",
							container.getAttributeRoleBase().getFullPath(),
							idBagMapping.getName()
					),
					sourceMappingDocument().getOrigin()
			);
		}


		this.collectionIdSource = new CollectionIdSourceImpl(
				(ColumnSource) collectionIdRelationalValueSource,
				new HibernateTypeSourceImpl( idBagMapping.getCollectionId().getType() ),
				idBagMapping.getCollectionId().getGenerator().getClazz(),
				Helper.extractParameters( idBagMapping.getCollectionId().getGenerator().getConfigParameters() )
		);
	}

View on GitHub (pinned to fad1729dce)

Solutions

  1. Declare a real column with a generator, e.g. <collection-id type='long'><column name='item_id'/><generator class='increment'/></collection-id>
  2. Add the corresponding physical column to the collection table
  3. If no surrogate id is needed, use <bag> instead of <idbag>

Example fix

// before
<idbag name='items' table='item'>
    <collection-id type='long'>
        <formula>nextval('item_seq')</formula>
    </collection-id>
    ...
</idbag>

// after
<idbag name='items' table='item'>
    <collection-id type='long'>
        <column name='item_id'/>
        <generator class='increment'/>
    </collection-id>
    ...
</idbag>
Defensive patterns

Strategy: validation

Validate before calling

// Pre-flight: <collection-id> must contain a <column>, never a <formula>
var cid = (org.w3c.dom.Element) doc.getElementsByTagName("collection-id").item(0);
if (cid.getElementsByTagName("formula").getLength() > 0 || !cid.getAttribute("formula").isEmpty())
    throw new IllegalStateException("idbag collection-id must be a physical column");

Try / catch

catch (org.hibernate.boot.MappingException e) at Metadata build: the message names the idbag attribute role - open that <idbag> and replace the formula under <collection-id> with a <column> plus generator

Prevention

When it happens

Trigger: An <idbag> whose <collection-id> declares its value via a formula - either a formula='...' style attribute or a nested <formula> element - instead of a <column> element.

Common situations: Copy-pasting a formula-based property mapping into <collection-id>; assuming a computed expression (e.g. a sequence call) can serve as the collection's surrogate id; tool-generated mappings that emit <formula> uniformly.

Related errors


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