apache/iceberg · error · RuntimeException

Failed to get table metadata for '%s'

Error message

Failed to get table metadata for '%s'

What it means

JdbcSnowflakeClient.loadTableMetadata executes SELECT SYSTEM$GET_ICEBERG_TABLE_INFORMATION(?) and wraps SQLException into 'Failed to get table metadata for %s'. It means the metadata lookup for the Iceberg table failed - the table doesn't exist, the caller lacks privileges, or the query/connection failed. Non-table identifiers are rejected earlier with an IllegalArgumentException, so this message always reflects a query/privilege/existence problem.

Source

Thrown at snowflake/src/main/java/org/apache/iceberg/snowflake/JdbcSnowflakeClient.java:348

  @Override
  public SnowflakeTableMetadata loadTableMetadata(SnowflakeIdentifier tableIdentifier) {
    Preconditions.checkArgument(
        tableIdentifier.type() == SnowflakeIdentifier.Type.TABLE,
        "loadTableMetadata requires a TABLE identifier, got '%s'",
        tableIdentifier);
    SnowflakeTableMetadata tableMeta;
    try {
      final String finalQuery = "SELECT SYSTEM$GET_ICEBERG_TABLE_INFORMATION(?) AS METADATA";
      tableMeta =
          connectionPool.run(
              conn ->
                  queryHarness.query(
                      conn,
                      finalQuery,
                      TABLE_METADATA_RESULT_SET_HANDLER,
                      tableIdentifier.toIdentifierString()));
    } catch (SQLException e) {
      throw snowflakeExceptionToIcebergException(
          tableIdentifier,
          e,
          String.format("Failed to get table metadata for '%s'", tableIdentifier));
    } catch (InterruptedException e) {
      throw new UncheckedInterruptedException(
          e, "Interrupted while getting table metadata for '%s'", tableIdentifier);
    }
    return tableMeta;
  }

  @Override
  public void close() {
    connectionPool.close();
  }

  private RuntimeException snowflakeExceptionToIcebergException(
      SnowflakeIdentifier identifier, SQLException ex, String defaultExceptionMessage) {
    // NoSuchNamespace exception for Database and Schema cases

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Verify the table exists and is a Snowflake-managed Iceberg table (SHOW ICEBERG TABLES / DESCRIBE TABLE)
  2. Check the role has sufficient privileges (SELECT or OWNERSHIP) on the table and its database/schema
  3. Catch the IcebergException and inspect the underlying SQLException error code; handle missing tables by re-listing or throwing NoSuchTableException upstream
  4. Retry transient failures and validate JDBC auth/connectivity configuration

Example fix

// before
catalog.loadTable(TableIdentifier.of("DB", "SCHEMA", "TBL")); // SQLException -> 'Failed to get table metadata'
// after
try {
  catalog.loadTable(TableIdentifier.of("DB", "SCHEMA", "TBL"));
} catch (IcebergException e) {
  // inspect e.getCause() SQLException: existence, privileges, or connectivity
  // optionally fall back to listIcebergTables to confirm the table exists
}
Defensive patterns

Strategy: try-catch

Validate before calling

// confirm the table is a listed Iceberg table before loading metadata
boolean isIceberg = catalog.listTables(Namespace.of(db, schema)).stream()
    .anyMatch(t -> t.name().equalsIgnoreCase(tableName));
if (!isIceberg) {
  // fail fast with NoSuchTableException instead of a metadata query error
}

Try / catch

try {
  catalog.loadTable(TableIdentifier.of(db, schema, table));
} catch (IcebergException e) {
  SQLException cause = findCause(e, SQLException.class);
  if (cause != null && tableMissing(cause.getErrorCode())) {
    // handle missing/non-Iceberg table
  } else if (isTransient(cause)) {
    // retry with backoff
  } else {
    throw e;
  }
}

Prevention

When it happens

Trigger: Calling loadTableMetadata(tableIdentifier) (used by SnowflakeCatalog.loadTable/refresh to obtain metadata location and registered-time) when the fully qualified table doesn't exist or is not an Iceberg table, the role lacks SELECT/OWNERSHIP privileges, or the JDBC query raises SQLException.

Common situations: Table dropped or renamed before metadata fetch; passing a dynamic/virtual view or non-Iceberg table; wrong case or qualifier in the identifier; expired credentials; transient Snowflake service errors.

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/iceberg@86d9c8fc54 (2026-09-12). Data as JSON: /api/errors/9f7c90548f72badb. Report an issue: GitHub.