apache/druid · error · ResultSetException

Unable to obtain metadata from result set

Error message

Unable to obtain metadata from result set

What it means

When SqlEntity.fetch() streams ResultSet rows to JSON, it first obtains the JDBC ResultSetMetaData via r.getMetaData(). If the driver throws a SQLException at that point, it wraps it in a JdbcQueryException/ResultSetException with the message 'Unable to obtain metadata from result set'. This indicates the driver could not produce metadata for the executed statement (e.g., statement no longer valid, connection dropped).

Solutions

  1. Check broker connectivity and retry the query; the underlying SQLException is attached as the cause.
  2. Verify the JDBC driver version is compatible with the SQL endpoint and upgrade it.
  3. Increase query timeouts so the ResultSet is not invalidated mid-fetch.
  4. Inspect the wrapped cause to identify the driver-level failure (connection reset, timeout, etc.).

Example fix

// before
resultMetadata = r.getMetaData();
// after
try (Statement stmt = conn.createStatement()) {
  stmt.setQueryTimeout(QUERY_TIMEOUT_SECONDS); // keep result set valid during fetch
  // execute and fetch metadata with retry on transient SQLException
}
Defensive patterns

Strategy: try-catch

Validate before calling

// verify connectivity before querying
try (Connection c = dataSource.getConnection()) {
  if (!c.isValid(5)) throw new IllegalStateException("connection invalid");
}

Try / catch

try {
  sqlEntity.fetch(tempDir, buffer);
} catch (ResultSetException e) {
  Throwable cause = e.getCause(); // SQLException: check connectivity/driver
  // retry or surface a user-facing query error
}

Prevention

When it happens

Trigger: Executing a SQL query whose ResultSet metadata cannot be retrieved: closed/dead connection mid-fetch, driver error on getMetaData(), or statement execution that produced no valid metadata (some drivers throw for non-query statements or after cancellation).

Common situations: Network interruption between metadata broker and the SQL endpoint; query timeout/cancel racing the fetch; driver-specific bugs (e.g., old JDBC drivers) when retrieving metadata; using a connection after it was invalidated.

Understand the failure class

Background: Database query failed: Internal Server Error 500s wrapping SQL, Prisma, and connection failures — what to check first — this error's family across 16 libraries.

Related errors


AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07). Data as JSON: /api/errors/9d9ffb2d60d82ffd. Report an issue: GitHub.

Appendix: source

Thrown at server/src/main/java/org/apache/druid/metadata/input/SqlEntity.java:139

    try (FileOutputStream fos = new FileOutputStream(tempFile);
         final JsonGenerator jg = objectMapper.getFactory().createGenerator(fos)) {
      final SerializerProvider serializers = objectMapper.getSerializerProviderInstance();

      // Execute the sql query and lazily retrieve the results into the file in json format.
      // foldCase is useful to handle differences in case sensitivity behavior across databases.
      sqlInputSourceDatabaseConnector.retryWithHandle(
          (handle) -> {
            ResultIterator<Map<String, Object>> resultIterator = handle.createQuery(
                sql
            ).map(
                (index, r, ctx) -> {
                  Map<String, Object> resultRow = foldCase ? new CaseFoldedMap() : new HashMap<>();
                  ResultSetMetaData resultMetadata;
                  try {
                    resultMetadata = r.getMetaData();
                  }
                  catch (SQLException e) {
                    throw new ResultSetException("Unable to obtain metadata from result set", e, ctx);
                  }
                  try {
                    for (int i = 1; i <= resultMetadata.getColumnCount(); i++) {
                      String key = resultMetadata.getColumnName(i);
                      String alias = resultMetadata.getColumnLabel(i);
                      Object value = r.getObject(i);
                      resultRow.put(alias != null ? alias : key, value);
                    }
                  }
                  catch (SQLException e) {
                    throw new ResultSetException("Unable to access specific metadata from " +
                                                 "result set metadata", e, ctx);
                  }
                  return resultRow;
                }
            ).iterator();
            jg.writeStartArray();
            while (resultIterator.hasNext()) {

View on GitHub (pinned to 9b90983fd2)