{"record":{"id":"2861e83ba44a9114","repo":"tursodatabase/turso","slug":"cannot-convert-value-to-date-type","errorCode":null,"errorMessage":"Cannot convert value to Date: {type}","messagePattern":"Cannot convert value to Date: (.+?)","errorType":"exception","errorClass":"SQLException","httpStatus":null,"severity":"error","filePath":"bindings/java/src/main/java/tech/turso/jdbc4/JDBC4ResultSet.java","lineNumber":188,"sourceCode":"\n  @Override\n  @Nullable\n  public Date getDate(int columnIndex) throws SQLException {\n    final Object result = resultSet.get(columnIndex);\n    wasNull = result == null;\n    if (result == null) {\n      return null;\n    }\n    return wrapTypeConversion(\n        () -> {\n          if (result instanceof byte[]) {\n            byte[] bytes = (byte[]) result;\n            if (bytes.length == Long.BYTES) {\n              long time = ByteBuffer.wrap(bytes).getLong();\n              return new Date(time);\n            }\n          }\n          throw new SQLException(\"Cannot convert value to Date: \" + result.getClass());\n        });\n  }\n\n  @Override\n  @SkipNullableCheck\n  public Time getTime(int columnIndex) throws SQLException {\n    final Object result = resultSet.get(columnIndex);\n    wasNull = result == null;\n    if (result == null) {\n      return null;\n    }\n    return wrapTypeConversion(\n        () -> {\n          if (result instanceof byte[]) {\n            byte[] bytes = (byte[]) result;\n            if (bytes.length == Long.BYTES) {\n              long time = ByteBuffer.wrap(bytes).getLong();\n              return new Time(time);","sourceCodeStart":170,"sourceCodeEnd":206,"githubUrl":"https://github.com/tursodatabase/turso/blob/bad083fafbefdeae9a42ec19bdaaad8918dcf411/bindings/java/src/main/java/tech/turso/jdbc4/JDBC4ResultSet.java#L170-L206","documentation":"getDate(int) accepts only this driver's own date representation: a byte[] of exactly 8 bytes holding epoch milliseconds — exactly what setDate writes (Long.BYTES buffer, putLong). If the column holds TEXT ('2024-01-31') or an INTEGER epoch value, the value arrives as String/Long and the conversion branch throws, naming the actual class. With SQLite's dynamic typing, the write path and read path must agree on the representation.","triggerScenarios":"Calling rs.getDate() on a TEXT date column filled with string literals or by other tools; on an INTEGER epoch-seconds column; on rows written by a different driver that stores dates as text.","commonSituations":"Tables shared with the sqlite3 CLI or other ORMs that write ISO-8601 text; mixed writers on one database; assuming the string-coercion behavior of other JDBC drivers.","solutions":["Read the raw value and parse in Java: java.sql.Date.valueOf(rs.getString(i)) for 'yyyy-[m]m-[d]d' text, or new Date(rs.getLong(i)) for epoch millis.","Write dates with setDate()/setTimestamp() so the 8-byte blob round-trips through getDate().","Normalize at the SQL level: select the column as text and parse, or migrate the column once so all rows share one representation."],"exampleFix":"// before\njava.sql.Date d = rs.getDate(1); // TEXT column '2024-01-31' -> throws\n\n// after\njava.sql.Date d = java.sql.Date.valueOf(rs.getString(1));","handlingStrategy":"type-guard","validationCode":"Object v = rs.getObject(1);\njava.sql.Date d = (v == null) ? null\n    : isDriverDateBlob(v) ? rs.getDate(1)\n    : java.sql.Date.valueOf(rs.getString(1)); // TEXT fallback","typeGuard":"static boolean isDriverDateBlob(Object v) {\n    return v instanceof byte[] b && b.length == Long.BYTES;\n}","tryCatchPattern":"try {\n    return rs.getDate(i);\n} catch (SQLException e) {\n    if (e.getMessage() != null && e.getMessage().contains(\"Cannot convert value to Date\")) {\n        return java.sql.Date.valueOf(rs.getString(i)); // TEXT-column fallback\n    }\n    throw e;\n}","preventionTips":["Fix one date representation per column (driver blob via setDate, TEXT, or epoch INTEGER) and use it on both write and read.","For interop with other SQLite tools, prefer TEXT 'yyyy-mm-dd' and Date.valueOf on read.","In generic code, check ResultSetMetaData.getColumnClassName() before typed getters."],"tags":["jdbc","type-conversion","date","sqlite-typing"],"backgroundTag":"jdbc-type-conversion-failed","analyzedSha":"bad083fafbefdeae9a42ec19bdaaad8918dcf411","analyzedAt":"2026-08-16T23:12:11.798Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}