{"record":{"id":"f2e4f499d21e7178","repo":"pentaho/pentaho-kettle","slug":"unable-to-retrieve-metadata-from-resultset","errorCode":null,"errorMessage":"Unable to retrieve metadata from resultset","messagePattern":"Unable to retrieve metadata from resultset","errorType":"exception","errorClass":"KettleDatabaseException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/org/pentaho/di/core/database/Database.java","lineNumber":2996,"sourceCode":"   */\n  public Object[] getRow( ResultSet rs ) throws KettleDatabaseException {\n    return getRow( rs, false );\n  }\n\n  /**\n   * Get a row from the resultset.\n   *\n   * @param rs             The resultset to get the row from\n   * @param lazyConversion set to true if strings need to have lazy conversion enabled\n   * @return one row or null if no row was found on the resultset or if an error occurred.\n   */\n  public Object[] getRow( ResultSet rs, boolean lazyConversion ) throws KettleDatabaseException {\n    if ( rowMeta == null ) {\n      ResultSetMetaData rsmd = null;\n      try {\n        rsmd = rs.getMetaData();\n      } catch ( SQLException e ) {\n        throw new KettleDatabaseException( \"Unable to retrieve metadata from resultset\", e );\n      }\n\n      rowMeta = getRowInfo( rsmd, false, lazyConversion );\n    }\n\n    return getRow( rs, null, rowMeta );\n  }\n\n  /**\n   * Get a row from the resultset.\n   *\n   * @param rs The resultset to get the row from\n   * @return one row or null if no row was found on the resultset or if an error occurred.\n   */\n  public Object[] getRow( ResultSet rs, ResultSetMetaData dummy, RowMetaInterface rowInfo )\n    throws KettleDatabaseException {\n    long startTime = System.currentTimeMillis();\n","sourceCodeStart":2978,"sourceCodeEnd":3014,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/core/src/main/java/org/pentaho/di/core/database/Database.java#L2978-L3014","documentation":"Thrown in Database.getRow(ResultSet, boolean) when rs.getMetaData() throws SQLException while lazily initializing the cached rowMeta. The library caches row metadata on first getRow call; failure to fetch it blocks all subsequent row reads.","triggerScenarios":"First call to Database.getRow(rs, lazyConversion) on a result set whose metadata cannot be retrieved — result set closed, connection dropped, or driver error on getMetaData().","commonSituations":"Long-running reads where the connection timed out before the first getRow; result set closed by another thread; driver bugs after executing large or complex queries.","solutions":["Check the connection is valid (isValid/ping) before executing and reading","Inspect the chained SQLException cause for the driver's reason","Re-execute the query to obtain a fresh result set","Upgrade the JDBC driver if getMetaData() fails on valid result sets"],"exampleFix":"// before\nObject[] row = db.getRow(rs, false);\n// after\nif (!rs.isClosed() && conn.isValid(5)) {\n  Object[] row = db.getRow(rs, false);\n} else {\n  rs = stmt.executeQuery(sql); // re-acquire\n}","handlingStrategy":"try-catch","validationCode":"if (rs.isClosed() || !conn.isValid(5)) {\n  rs = stmt.executeQuery(sql); // re-acquire before reading\n}","typeGuard":"null","tryCatchPattern":"try {\n  row = db.getRow(rs, false);\n} catch (KettleDatabaseException e) {\n  if (e.getMessage().contains(\"Unable to retrieve metadata\")) {\n    rs = stmt.executeQuery(sql); // retry with fresh result set\n  } else { throw e; }\n}","preventionTips":["Read rows promptly after executing the query","Apply connection keep-alive/validity checks for long jobs","Avoid closing statements from other threads mid-read","Re-execute rather than reusing stale result sets"],"tags":["jdbc","metadata","resultset"],"backgroundTag":"database-query-failed","analyzedSha":"f3058517a153da500bf4551f46d79b91bf8ec552","analyzedAt":"2026-09-13T14:04:16.340Z","contentChangedAt":"2026-09-13T14:04:16.340Z","schemaVersion":2},"datasetVersion":"2026-09-20T23:17:15.980Z"}