tursodatabase/turso · error · SQLException
step() returned invalid result: " + lastStepResult
Error message
step() returned invalid result: " + lastStepResult
What it means
Same invalid-step-state path as its sibling, but the native result carried no error message (null or empty), so the TursoStepResult's toString is embedded instead. It is the low-information variant: the native side reported failure without text. Debug logging ('lastStepResult: {}') is the only built-in visibility into the state.
Source
Thrown at bindings/java/src/main/java/tech/turso/core/TursoResultSet.java:97
}
if (maxRows != 0 && row == maxRows) {
return false;
}
lastStepResult = this.statement.step();
log.debug("lastStepResult: {}", lastStepResult);
if (lastStepResult.isRow()) {
row++;
}
if (lastStepResult.isInInvalidState()) {
open = false;
String errorMessage = lastStepResult.getErrorMessage();
if (errorMessage != null && !errorMessage.isEmpty()) {
throw new SQLException("step() returned invalid result: " + errorMessage);
} else {
throw new SQLException("step() returned invalid result: " + lastStepResult);
}
}
pastLastRow = lastStepResult.isDone();
if (pastLastRow && row == 0) {
isEmptyResultSet = true;
}
return !pastLastRow;
}
/** Checks whether the last step result has returned row result. */
public boolean hasLastStepReturnedRow() {
return lastStepResult != null && lastStepResult.isRow();
}
/** Checks whether the cursor is positioned after the last row. */
public boolean isPastLastRow() {
return pastLastRow;View on GitHub (pinned to bad083fafb)
Solutions
- Enable DEBUG logging for tech.turso.core.TursoResultSet to capture the full lastStepResult state at each step
- Wrap the SQL and the failing step index into your own error context so the repro is actionable
- Check for concurrency on the connection (other threads stepping/closing) and for interrupt() usage
- If reproducible, minimize the SQL and report it — a message-less invalid state is a native diagnostics gap
Example fix
// before
while (rs.next()) { emit(rs); } // 'step() returned invalid result: TursoStepResult@...'
// after
try {
while (rs.next()) { emit(rs); }
} catch (SQLException e) {
throw new IllegalStateException("query failed: " + sql, e); // keep SQL + result context
}
// plus run with: -Djava.util.logging.level=FINE (or SLF4J debug for tech.turso.core) Defensive patterns
Strategy: try-catch
Try / catch
try {
while (rs.next()) {
emit(rs);
}
} catch (SQLException e) {
// no native message in this variant — capture lastStepResult via debug logs
// and attach the SQL + step index to whatever error you rethrow
throw new IllegalStateException("step failed for query: " + sql, e);
} Prevention
- Run with DEBUG logging for tech.turso.core.TursoResultSet in environments where the failure occurs
- Always attach the SQL to iteration errors — this variant carries no native text
- Check for concurrent use of the statement/connection when it appears intermittently
When it happens
Trigger: A step that enters an invalid state whose TursoStepResult has a null/empty error message — native failure paths that do not populate the message field (some interrupt, busy, or internal error states).
Common situations: Intermittent failures in CI that only show 'step() returned invalid result: STEP_RESULT_ID_IO/...' with no SQL text; reproducing locally works because the failure depends on timing or concurrency.
Related errors
- step() returned invalid result: " + errorMessage
- SQLite only supports TYPE_FORWARD_ONLY cursors
- SQLite only supports CONCUR_READ_ONLY cursors
- SQLite only supports closing cursors at commit
- The result set is not open
AI-assisted analysis of tursodatabase/turso@bad083fafb (2026-08-16).
Data as JSON: /api/errors/af65885cfda07f50.
Report an issue: GitHub.