{"record":{"id":"e8dd3cb5c2eda010","repo":"hibernate/hibernate-orm","slug":"illegal-identity-column-type","errorCode":null,"errorMessage":"illegal identity column type","messagePattern":"illegal identity column type","errorType":"exception","errorClass":"MappingException","httpStatus":null,"severity":"error","filePath":"hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/identity/InformixIdentityColumnSupport.java","lineNumber":30,"sourceCode":"/**\n * @author Andrea Boriero\n */\npublic class InformixIdentityColumnSupport extends IdentityColumnSupportImpl {\n\n\tpublic static final InformixIdentityColumnSupport INSTANCE = new InformixIdentityColumnSupport();\n\n\t@Override\n\tpublic boolean supportsIdentityColumns() {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic String getIdentitySelectString(String table, String column, int type)\n\t\t\tthrows MappingException {\n\t\treturn \"select dbinfo('\" + switch ( type ) {\n\t\t\tcase Types.BIGINT -> \"bigserial\";\n\t\t\tcase Types.INTEGER -> \"sqlca.sqlerrd1\";\n\t\t\tdefault -> throw new MappingException( \"illegal identity column type\" );\n\t\t} + \"') from informix.systables where tabid=1\";\n\t}\n\n\t@Override\n\tpublic String getIdentityColumnString(int type) throws MappingException {\n\t\treturn switch ( type ) {\n\t\t\tcase Types.BIGINT -> \"bigserial\";\n\t\t\tcase Types.INTEGER -> \"serial\";\n\t\t\tdefault -> throw new MappingException( \"illegal identity column type\" );\n\t\t} + \" not null\";\n\t}\n\n\t@Override\n\tpublic boolean hasDataTypeInIdentityColumn() {\n\t\treturn false;\n\t}\n}\n","sourceCodeStart":12,"sourceCodeEnd":48,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/identity/InformixIdentityColumnSupport.java#L12-L48","documentation":"Informix identity columns come in only two flavors: 'serial' (Types.INTEGER) and 'bigserial' (Types.BIGINT). When Hibernate needs the SQL to retrieve the last generated identity value (getIdentitySelectString builds select dbinfo(...) ...) and the id column's java.sql.Types code is anything else, InformixIdentityColumnSupport throws this MappingException with 'illegal identity column type'.","triggerScenarios":"An entity mapped with @GeneratedValue(strategy = GenerationType.IDENTITY) (or the legacy 'identity' generator) whose identifier Java type resolves to a JDBC type other than INTEGER/BIGINT - e.g. Short/smallint, String, BigDecimal/numeric. Thrown when the mapping is bound (SessionFactory build), during export of the dbinfo select string.","commonSituations":"Porting an app from another database where identity on smallint or numeric worked; legacy Informix schemas; accidentally mapping the @Id as Short or java.math.BigInteger; changing an id type during a refactor and failing fast at bootstrap.","solutions":["Map the identifier as Integer/int or Long/long so Types.INTEGER/BIGINT applies.","If the column type must stay smallint/numeric, switch the generator to SEQUENCE or the enhanced 'sequence'/'table' generator.","Let the application assign ids (assigned/natural generator) instead of the database.","If the schema really is serial-compatible, force the JDBC type with @JdbcTypeCode(SqlTypes.INTEGER) - but changing the Java type to Integer/Long is the clean fix."],"exampleFix":"// before - Short maps to SMALLINT, not serial-compatible\n@Id\n@GeneratedValue(strategy = GenerationType.IDENTITY)\nprivate Short id;\n\n// after - maps to Types.BIGINT -> bigserial\n@Id\n@GeneratedValue(strategy = GenerationType.IDENTITY)\nprivate Long id;","handlingStrategy":"validation","validationCode":"// Before bootstrap on Informix, ensure identity ids are Integer or Long\nClass<?> idType = reflectIdType(MyEntity.class);\nif (!Integer.class.equals(idType) && !Long.class.equals(idType)\n        && !int.class.equals(idType) && !long.class.equals(idType)) {\n    throw new IllegalStateException(\"Informix identity requires Integer/Long id, got \" + idType);\n}","typeGuard":"static boolean informixIdentityCompatible(Class<?> idJavaType) {\n    return idJavaType == Integer.class || idJavaType == int.class\n        || idJavaType == Long.class || idJavaType == long.class;\n}","tryCatchPattern":"try {\n    sessionFactory = new Configuration().addAnnotatedClass(MyEntity.class).buildSessionFactory();\n} catch (MappingException e) {\n    if (e.getMessage().contains(\"illegal identity column type\")) {\n        // fix the @Id type or switch generator strategy, then rebuild\n    }\n    throw e;\n}","preventionTips":["Keep @GeneratedValue(IDENTITY) ids as Integer or Long","Add a mapping smoke test that builds the SessionFactory in CI for each target dialect","Prefer sequences for non-integer primary keys"],"tags":["informix","identity","mapping","id-generation","bootstrap","mapping-exception"],"backgroundTag":"unsupported-identity-column-type","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}