tursodatabase/turso · error · SQLException
Query timeout must be greater than 0
Error message
Query timeout must be greater than 0
What it means
JDBC4Statement.setQueryTimeout(int) rejects negative values with SQLException("Query timeout must be greater than 0"). The message is misleading: the guard is `seconds < 0`, so 0 (which in JDBC means 'no timeout') is accepted — only negatives throw. Note also that the stored value is not enforced yet; getQueryTimeout() is a TODO stub returning 0.
Solutions
- Clamp the configured value to >= 0 before calling (map -1/'unlimited' to 0)
- Fix the source configuration to a valid non-negative timeout
- Validate externally supplied timeout input early and fail with your own error message
Example fix
// before stmt.setQueryTimeout(configuredTimeout); // -1 -> SQLException // after int timeout = Math.max(0, configuredTimeout); stmt.setQueryTimeout(timeout);
Defensive patterns
Strategy: validation
Validate before calling
int safeTimeout = timeoutSeconds < 0 ? 0 : timeoutSeconds; // -1/'unlimited' -> 0 stmt.setQueryTimeout(safeTimeout);
Try / catch
try {
stmt.setQueryTimeout(timeoutSeconds);
} catch (SQLException e) {
if (e.getMessage() != null && e.getMessage().contains("Query timeout")) {
stmt.setQueryTimeout(0); // retry with 'no timeout'
} else {
throw e;
}
} Prevention
- Clamp every externally sourced timeout to >= 0 before calling setQueryTimeout
- Use 0 for 'disabled'; do not use -1 conventions with this driver
- Note the driver does not enforce the timeout yet — do not rely on it for cancellation
When it happens
Trigger: Calling stmt.setQueryTimeout(-1) or any negative value. Frequently the negative comes from a convention where -1 means 'unlimited' or 'use default' (MyBatis/Spring-style timeout properties) and is passed through unclamped; also from parsing a user- or config-supplied timeout string without validation.
Common situations: Properties files with timeout=-1; frameworks that mirror java.sql defaults of -1 and call setQueryTimeout unconditionally; migration from drivers that accept -1 silently.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
AI-assisted analysis of tursodatabase/turso@244cde92a7 (2026-08-20).
Data as JSON: /api/errors/5f3f2833fdfd1cb0.
Report an issue: GitHub.
Appendix: source
Thrown at bindings/java/src/main/java/tech/turso/jdbc4/JDBC4Statement.java:164
public void setMaxRows(int max) throws SQLException {
// TODO
}
@Override
public void setEscapeProcessing(boolean enable) throws SQLException {
// TODO
}
@Override
public int getQueryTimeout() throws SQLException {
// TODO
return 0;
}
@Override
public void setQueryTimeout(int seconds) throws SQLException {
if (seconds < 0) {
throw new SQLException("Query timeout must be greater than 0");
}
this.queryTimeoutSeconds = seconds;
}
@Override
public void cancel() throws SQLException {
// TODO
}
@Override
@SkipNullableCheck
public SQLWarning getWarnings() throws SQLException {
// TODO
return null;
}
@Override
public void clearWarnings() throws SQLException {View on GitHub (pinned to 244cde92a7)