{"record":{"id":"1b98248ed1f515c3","repo":"mybatis/mybatis-3","slug":"cannot-convert-to-by-ordinal-value","errorCode":null,"errorMessage":"Cannot convert {} to {} by ordinal value.","messagePattern":"Cannot convert (.+?) to (.+?) by ordinal value\\.","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"src/main/java/org/apache/ibatis/type/EnumOrdinalTypeHandler.java","lineNumber":78,"sourceCode":"      return null;\n    }\n    return toOrdinalEnum(ordinal);\n  }\n\n  @Override\n  public E getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {\n    int ordinal = cs.getInt(columnIndex);\n    if (ordinal == 0 && cs.wasNull()) {\n      return null;\n    }\n    return toOrdinalEnum(ordinal);\n  }\n\n  private E toOrdinalEnum(int ordinal) {\n    try {\n      return enums[ordinal];\n    } catch (Exception ex) {\n      throw new IllegalArgumentException(\n          \"Cannot convert \" + ordinal + \" to \" + type.getSimpleName() + \" by ordinal value.\", ex);\n    }\n  }\n}\n","sourceCodeStart":60,"sourceCodeEnd":83,"githubUrl":"https://github.com/mybatis/mybatis-3/blob/008069adb1b089579b5dcba87ee591908b263274/src/main/java/org/apache/ibatis/type/EnumOrdinalTypeHandler.java#L60-L83","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\npublic enum Status { ACTIVE, CLOSED } // DB has 5; row was written when enum had 6 values\n\n// after\n// migrate column to names and map by name\n<result column=\"status\" property=\"status\" typeHandler=\"org.apache.ibatis.type.EnumTypeHandler\"/>","handlingStrategy":"try-catch","validationCode":"// guard on read inside a custom handler\nint ordinal = rs.getInt(column);\nif (ordinal < 0 || ordinal >= Status.values().length) {\n  log.warn(\"Unknown ordinal {} for Status\", ordinal);\n  return null;\n}","typeGuard":"static Status fromOrdinal(int o) {\n  Status[] v = Status.values();\n  return (o >= 0 && o < v.length) ? v[o] : null;\n}","tryCatchPattern":"try { ... } catch (IllegalArgumentException e) { if (e.getMessage().contains(\"by ordinal value\")) { /* map unknown ordinals to a default/null instead of failing the query */ } }","preventionTips":["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"],"tags":["mybatis","enum","ordinal","data-mismatch"],"backgroundTag":null,"analyzedSha":"008069adb1b089579b5dcba87ee591908b263274","analyzedAt":"2026-08-14T13:07:10.264Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}