{"record":{"id":"5fffdd0689bd9d65","repo":"tursodatabase/turso","slug":"step-returned-invalid-result-errormessage","errorCode":null,"errorMessage":"step() returned invalid result: \" + errorMessage","messagePattern":"step\\(\\) returned invalid result: \" \\+ errorMessage","errorType":"exception","errorClass":"SQLException","httpStatus":null,"severity":"error","filePath":"bindings/java/src/main/java/tech/turso/core/TursoResultSet.java","lineNumber":95,"sourceCode":"    if (isEmptyResultSet || pastLastRow) {\n      return false; // completed ResultSet\n    }\n\n    if (maxRows != 0 && row == maxRows) {\n      return false;\n    }\n\n    lastStepResult = this.statement.step();\n    log.debug(\"lastStepResult: {}\", lastStepResult);\n    if (lastStepResult.isRow()) {\n      row++;\n    }\n\n    if (lastStepResult.isInInvalidState()) {\n      open = false;\n      String errorMessage = lastStepResult.getErrorMessage();\n      if (errorMessage != null && !errorMessage.isEmpty()) {\n        throw new SQLException(\"step() returned invalid result: \" + errorMessage);\n      } else {\n        throw new SQLException(\"step() returned invalid result: \" + lastStepResult);\n      }\n    }\n\n    pastLastRow = lastStepResult.isDone();\n    if (pastLastRow && row == 0) {\n      isEmptyResultSet = true;\n    }\n    return !pastLastRow;\n  }\n\n  /** Checks whether the last step result has returned row result. */\n  public boolean hasLastStepReturnedRow() {\n    return lastStepResult != null && lastStepResult.isRow();\n  }\n\n  /** Checks whether the cursor is positioned after the last row. */","sourceCodeStart":77,"sourceCodeEnd":113,"githubUrl":"https://github.com/tursodatabase/turso/blob/bad083fafbefdeae9a42ec19bdaaad8918dcf411/bindings/java/src/main/java/tech/turso/core/TursoResultSet.java#L77-L113","documentation":"While iterating, statement.step() returned a TursoStepResult in an invalid state — a native execution error surfaced mid-iteration. The native error text is appended to the message. next() marks the set closed (open = false) before throwing, so the ResultSet is unusable afterwards.","triggerScenarios":"Stepping a query whose evaluation fails partway: a UNIQUE/NOT NULL/CHECK constraint violation on an INSERT/UPDATE driven through step(), SQLITE_BUSY on a locked database, interrupt() from another thread, or an I/O error while advancing the cursor.","commonSituations":"Batch INSERT loops hitting a duplicate key mid-batch; concurrent writers holding the lock without busy_timeout; cancellation logic interrupting a running query; database files on failing/removable storage.","solutions":["Read the appended native message — it carries the real cause (constraint name, 'database is locked', ...)","Fix the root cause: relax/repair constraints, use INSERT OR IGNORE / ON CONFLICT where semantics allow, set a busy timeout or retry on lock errors","Abort the batch on this exception — the ResultSet is already closed and cannot resume","Avoid calling interrupt() on a connection whose statements are being iterated"],"exampleFix":"// before\nwhile (rs.next()) { emit(rs); } // dies mid-batch on UNIQUE violation\n\n// after\ntry {\n  while (rs.next()) { emit(rs); }\n} catch (SQLException e) {\n  // e.getMessage() ends with the native cause, e.g. constraint failure\n  abortBatchAndLog(e);\n}\n// and make conflicts explicit in SQL:\n// INSERT INTO t VALUES(?, ?) ON CONFLICT(id) DO NOTHING","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  while (rs.next()) {\n    emit(rs);\n  }\n} catch (SQLException e) {\n  // message ends with the native cause (constraint name, 'database is locked', ...)\n  abortBatch(e.getMessage());\n  // rs is now closed — re-execute from the last checkpoint if you need to resume\n}","preventionTips":["Design batch loops to be resumable: track the last processed row so a mid-batch failure is recoverable","Use ON CONFLICT / OR IGNORE for expected duplicates instead of failing the step","Configure busy behavior and avoid interrupt() while statements iterate"],"tags":["java","jdbc","resultset","step","native","runtime-error","bindings"],"backgroundTag":"sql-execution-runtime-error","analyzedSha":"bad083fafbefdeae9a42ec19bdaaad8918dcf411","analyzedAt":"2026-08-16T23:12:11.798Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}