mybatis/mybatis-3 · error · IllegalArgumentException
Cannot convert {} to {} by ordinal value.
Error message
Cannot convert {} to {} by ordinal value. What it means
EnumOrdinalTypeHandler maps database integers to enum constants by array position (ordinal). When the integer read from the column is negative or >= enums.length, the array access fails and toOrdinalEnum throws this IllegalArgumentException showing the raw value and the target enum name.
Source
Thrown at src/main/java/org/apache/ibatis/type/EnumOrdinalTypeHandler.java:78
return null;
}
return toOrdinalEnum(ordinal);
}
@Override
public E getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
int ordinal = cs.getInt(columnIndex);
if (ordinal == 0 && cs.wasNull()) {
return null;
}
return toOrdinalEnum(ordinal);
}
private E toOrdinalEnum(int ordinal) {
try {
return enums[ordinal];
} catch (Exception ex) {
throw new IllegalArgumentException(
"Cannot convert " + ordinal + " to " + type.getSimpleName() + " by ordinal value.", ex);
}
}
}
View on GitHub (pinned to 008069adb1)
Solutions
- Reconcile the data: update the column to valid ordinals, or restore/reorder the enum constants to match the data
- Switch to EnumTypeHandler (name-based mapping) so stored values survive reordering — migrate the column to the enum names
- Add a data constraint/validation on write so only valid ordinals can be persisted
Example fix
// before
public enum Status { ACTIVE, CLOSED } // DB has 5; row was written when enum had 6 values
// after
// migrate column to names and map by name
<result column="status" property="status" typeHandler="org.apache.ibatis.type.EnumTypeHandler"/> Defensive patterns
Strategy: try-catch
Validate before calling
// guard on read inside a custom handler
int ordinal = rs.getInt(column);
if (ordinal < 0 || ordinal >= Status.values().length) {
log.warn("Unknown ordinal {} for Status", ordinal);
return null;
} Type guard
static Status fromOrdinal(int o) {
Status[] v = Status.values();
return (o >= 0 && o < v.length) ? v[o] : null;
} Try / catch
try { ... } catch (IllegalArgumentException e) { if (e.getMessage().contains("by ordinal value")) { /* map unknown ordinals to a default/null instead of failing the query */ } } Prevention
- Prefer name-based EnumTypeHandler for values that outlive code changes
- Never reorder or delete enum constants that are persisted by ordinal
- Add a CHECK constraint limiting the column to the known ordinal range
When it happens
Trigger: The column contains an ordinal that no longer exists in the enum: enum constants were reordered or deleted after the rows were written; the column stores a different numbering scheme (e.g. 1-based) than Java ordinals (0-based); hand-edited/seeded data.
Common situations: Inserting/reordering enum constants between releases; importing data where the status column is 1-based; a different application writing ordinals from its own enum ordering.
Related errors
- Type argument cannot be null
- {} does not represent an enum type.
- Type argument cannot be null
- Unknown execution method for: {name}
- Mapper method '{name}' attempted to return null from a metho
AI-assisted analysis of mybatis/mybatis-3@008069adb1 (2026-08-14).
Data as JSON: /api/errors/1b98248ed1f515c3.
Report an issue: GitHub.