prestodb/presto · error · SemanticException

MISSING_TABLE

MISSING_TABLE

Error message

Table does not exist

What it means

extractScope in MaterializedViewQueryOptimizer resolves the base table of a materialized view via the metadata resolver. If the catalog/schema/table name of the base table does not resolve to a TableHandle, the optimizer throws MISSING_TABLE because it cannot build a Scope over a nonexistent base table to rewrite the query.

Source

Thrown at presto-main-base/src/main/java/com/facebook/presto/sql/analyzer/MaterializedViewQueryOptimizer.java:909

                if (coercion != null) {
                    rewritten = new Cast(
                            original.getLocation(),
                            rewritten,
                            coercion.getTypeSignature().toString(),
                            false,
                            analysis.isTypeOnlyCoercion(original));
                }
                return rewritten;
            }
        }

        private Scope extractScope(Table table, QuerySpecification node, Expression whereClause)
        {
            QualifiedObjectName baseTableName = createQualifiedObjectName(session, table, table.getName(), metadata);

            Optional<TableHandle> tableHandle = metadata.getMetadataResolver(session).getTableHandle(baseTableName);
            if (!tableHandle.isPresent()) {
                throw new SemanticException(MISSING_TABLE, node, "Table does not exist");
            }

            ImmutableList.Builder<Field> fields = ImmutableList.builder();

            for (ColumnHandle columnHandle : metadata.getColumnHandles(session, tableHandle.get()).values()) {
                ColumnMetadata columnMetadata = metadata.getColumnMetadata(session, tableHandle.get(), columnHandle);
                fields.add(Field.newUnqualified(whereClause.getLocation(), columnMetadata.getName(), columnMetadata.getType()));
            }

            return Scope.builder()
                    .withRelationType(RelationId.anonymous(), new RelationType(fields.build()))
                    .build();
        }

        private MaterializedViewStatus getMaterializedViewStatus(QuerySpecification querySpecification)
        {
            TupleDomain<String> baseQueryDomain = TupleDomain.all();

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Verify the base table exists: run SHOW TABLES / SELECT from the base table directly in the same catalog/schema.
  2. Recreate the missing/renamed base table, or drop and recreate the materialized view pointing at a valid table.
  3. Check the catalog is configured on the coordinator (etc/catalog/<name>.properties) and the connector is loaded.

Example fix

// before (mv_definition references dropped table)
CREATE MATERIALIZED VIEW mv AS SELECT * FROM staging.events_old;
// after
DROP MATERIALIZED VIEW mv;
CREATE MATERIALIZED VIEW mv AS SELECT * FROM staging.events;
Defensive patterns

Strategy: try-catch

Validate before calling

// verify the MV's base table resolves before querying
-- SHOW TABLES FROM <catalog>.<schema>;  -- confirm base table present
-- SELECT 1 FROM <base_table> LIMIT 1;   -- probes resolution

Try / catch

try {
  runQuery("SELECT * FROM mv");
} catch (SemanticException e) {
  if ("MISSING_TABLE".equals(e.getCode().name())) {
    // recreate base table or drop/recreate the materialized view
  } else throw e;
}

Prevention

When it happens

Trigger: Querying a materialized view whose underlying base table was dropped, renamed, or lives in a catalog that is not registered in the current session; also when the materialized view definition references a table name that the connector cannot resolve.

Common situations: Base table dropped or renamed after the materialized view was created; stale materialized view definitions after schema migrations; missing catalog configuration in the coordinator's catalog directory.

Related errors


AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04). Data as JSON: /api/errors/3885b61f8f8f51e1. Report an issue: GitHub.