{"record":{"id":"a79464652e857ab0","repo":"tursodatabase/turso","slug":"resultset-is-not-open","errorCode":null,"errorMessage":"ResultSet is not open","messagePattern":"ResultSet is not open","errorType":"exception","errorClass":"SQLException","httpStatus":null,"severity":"error","filePath":"bindings/java/src/main/java/tech/turso/core/TursoResultSet.java","lineNumber":161,"sourceCode":"\n  public void close() throws SQLException {\n    this.open = false;\n  }\n\n  public Object get(String columnName) throws SQLException {\n    final int columnsLength = this.columnNames.length;\n    for (int i = 0; i < columnsLength; i++) {\n      if (this.columnNames[i].equals(columnName)) {\n        return get(i + 1);\n      }\n    }\n\n    throw new SQLException(\"column name \" + columnName + \" not found\");\n  }\n\n  public Object get(int columnIndex) throws SQLException {\n    if (!this.isOpen()) {\n      throw new SQLException(\"ResultSet is not open\");\n    }\n\n    if (this.lastStepResult == null || this.lastStepResult.getResult() == null) {\n      throw new SQLException(\"ResultSet is null\");\n    }\n\n    final Object[] resultSet = this.lastStepResult.getResult();\n    if (columnIndex > resultSet.length || columnIndex < 0) {\n      throw new SQLException(\"columnIndex out of bound\");\n    }\n\n    return resultSet[columnIndex - 1];\n  }\n\n  public String[] getColumnNames() {\n    return this.columnNames;\n  }\n","sourceCodeStart":143,"sourceCodeEnd":179,"githubUrl":"https://github.com/tursodatabase/turso/blob/bad083fafbefdeae9a42ec19bdaaad8918dcf411/bindings/java/src/main/java/tech/turso/core/TursoResultSet.java#L143-L179","documentation":"get(int columnIndex) starts with an isOpen() check and throws this message ('ResultSet is not open' — a different string from checkOpen()'s 'ResultSet closed', which makes message-based matching brittle). The set is closed by close(), statement close/reset, or a prior invalid step.","triggerScenarios":"Calling get(int) after rs.close(); after the owning TursoStatement was closed; on the stale ResultSet after TursoStatement.reset(); after a step error set open = false.","commonSituations":"Deferred materialization patterns that read columns after the statement scope ended; retry loops that re-read from an already-closed set; helper getters invoked from finally blocks.","solutions":["Read column values before closing the ResultSet or its statement","Check rs.isOpen() before optional reads","If matching this error in catch blocks, match both message variants ('ResultSet is not open' and 'ResultSet closed')"],"exampleFix":"// before\nResultSet rs = st.getResultSet();\nst.close();\nObject v = rs.get(1); // throws: ResultSet is not open\n\n// after\nResultSet rs = st.getResultSet();\nObject v = rs.next() ? rs.get(1) : null;\nst.close();","handlingStrategy":"validation","validationCode":"if (rs.isOpen()) {\n  Object v = rs.get(columnIndex);\n}","typeGuard":null,"tryCatchPattern":"try {\n  return rs.get(columnIndex);\n} catch (SQLException e) {\n  String m = e.getMessage();\n  if (\"ResultSet is not open\".equals(m) || \"ResultSet closed\".equals(m)) {\n    return null; // set closed underneath — re-execute if the data is required\n  }\n  throw e;\n}","preventionTips":["Read values before closing the statement or result set","Match both closed-set message variants ('ResultSet is not open' and 'ResultSet closed') in error handling","Avoid holding a ResultSet across method calls that may close its statement"],"tags":["java","jdbc","resultset","lifecycle","bindings"],"backgroundTag":"resultset-already-closed","analyzedSha":"bad083fafbefdeae9a42ec19bdaaad8918dcf411","analyzedAt":"2026-08-16T23:12:11.798Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}