alibaba/druid · error · SQLException
validationQuery didn't return a row
Error message
validationQuery didn't return a row
What it means
Thrown during connection validation when a configured validationQuery is executed via ValidConnectionCheckerAdapter.execValidQuery but the query returns no rows. Druid uses the validation query (e.g. SELECT 1) to confirm a connection is alive; a query that returns zero rows is treated as proof the connection is unusable. This guard runs on testWhileIdle, testOnBorrow, testOnReturn, and keepAlive paths.
Source
Thrown at core/src/main/java/com/alibaba/druid/pool/DruidAbstractDataSource.java:1490
return;
}
if (null != query) {
boolean valid;
try {
valid = ValidConnectionCheckerAdapter.execValidQuery(conn, query, validationQueryTimeout);
} catch (SQLException ex) {
throw ex;
} catch (Exception ex) {
throw new SQLException("validationQuery failed", ex);
} finally {
if (conn instanceof ConnectionProxyImpl) {
((ConnectionProxyImpl) conn).setLastValidateTimeMillis(System.currentTimeMillis());
}
}
if (!valid) {
throw new SQLException("validationQuery didn't return a row");
}
if (onFatalError) {
lock.lock();
try {
if (onFatalError) {
onFatalError = false;
}
} finally {
lock.unlock();
}
}
}
}
/**
* @deprecated
*/View on GitHub (pinned to fa8dc99126)
Solutions
- Set validationQuery to a statement guaranteed to return exactly one row for your database (MySQL: 'SELECT 1', Oracle: 'SELECT 1 FROM DUAL', PostgreSQL: 'SELECT 1').
- Verify the DB user has SELECT privileges on whatever the validationQuery references.
- Prefer using a ValidConnectionChecker (Druid auto-selects one per dbType) by leaving validationQuery default rather than overriding it with a fragile custom query.
- If using testWhileIdle/keepAlive, confirm the validation query works by running it manually in the same session context.
Example fix
// before
dataSource.setValidationQuery("SELECT 1 FROM app_config WHERE flag='on'");
// after
dataSource.setValidationQuery("SELECT 1"); Defensive patterns
Strategy: try-catch
Validate before calling
// Confirm the validation query returns a row in your DB before assigning it
String vq = dataSource.getValidationQuery();
try (Connection c = dataSource.getDriver().connect(dataSource.getUrl(), dataSource.getConnectProperties());
Statement s = c.createStatement();
ResultSet rs = s.executeQuery(vq)) {
if (!rs.next()) {
throw new IllegalStateException("validationQuery returns no rows: " + vq);
}
} Try / catch
try {
conn = dataSource.getConnection();
} catch (SQLException e) {
if (e.getMessage() != null && e.getMessage().contains("validationQuery didn't return a row")) {
LOG.error("validationQuery misconfigured; check " + dataSource.getValidationQuery(), e);
}
throw e;
} Prevention
- Use the canonical single-row validation query for your DB dialect.
- Leave validationQuery at default so Druid's built-in ValidConnectionChecker is used.
- Never reference application tables in the validation query.
When it happens
Trigger: validateConnection(conn) is called with a non-null query, execValidQuery returns false (empty ResultSet), and the !valid branch at line 1489 fires. Happens when validationQuery is set to something that conditionally returns no rows, or when the DB session is in a state where the query yields nothing.
Common situations: A validationQuery like 'SELECT 1 FROM dual WHERE 1=0' that deliberately returns no rows; a query referencing a table/object the connecting user lacks privileges on; a stale connection whose session state makes the validation query return empty; custom validation queries ported from another DB dialect.
Related errors
- keepAliveBetweenTimeMillis must be greater than timeBetweenE
- maxActive less than minIdle, {} < {}
- maxActive can't not set zero
- illegal maxActive {}
- illegal initialSize {}, maxActive {}
AI-assisted analysis of alibaba/druid@fa8dc99126 (2026-08-14).
Data as JSON: /api/errors/318d00d425d03694.
Report an issue: GitHub.