prestodb/presto · error · PrestoException

ALREADY_EXISTS

ALREADY_EXISTS

Error message

Materialized view already exists: 

What it means

When creating (materializing) an Iceberg materialized view, the backing metastore table is created. If a table with the same name already exists (TableAlreadyExistsException from the metastore), Presto translates it into PrestoException ALREADY_EXISTS with 'Materialized view already exists: <name>'.

Source

Thrown at presto-iceberg/src/main/java/com/facebook/presto/iceberg/IcebergHiveMetadata.java:822

        tableProperties.putAll(createIcebergViewProperties(session, nodeVersion.toString()));

        ConnectorTableMetadata viewMetadata = new ConnectorTableMetadata(viewName, columns);

        Table table = createTableObjectForViewCreation(
                session,
                viewMetadata,
                tableProperties.build(),
                new HiveTypeTranslator(),
                metastoreContext,
                encodeViewData(viewSql));

        PrincipalPrivileges privileges = buildInitialPrivilegeSet(session.getUser());

        try {
            metastore.createTable(metastoreContext, table, privileges, emptyList());
        }
        catch (TableAlreadyExistsException e) {
            throw new PrestoException(ALREADY_EXISTS, "Materialized view already exists: " + viewName);
        }
    }

    @Override
    protected void dropIcebergView(ConnectorSession session, SchemaTableName schemaTableName)
    {
        MetastoreContext metastoreContext = getMetastoreContext(session);

        try {
            metastore.dropTable(
                    metastoreContext,
                    schemaTableName.getSchemaName(),
                    schemaTableName.getTableName(),
                    true);
        }
        catch (TableNotFoundException e) {
            throw new PrestoException(NOT_FOUND, "Materialized view not found: " + schemaTableName);
        }

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Choose a different materialized view name or drop/rename the existing object first
  2. Check existence with SHOW TABLES / system.metadata before creating, and skip if present
  3. Use CREATE OR REPLACE semantics if available, or DROP MATERIALIZED VIEW before recreate
  4. Serialize creation logic in orchestration so concurrent jobs don't race on the same name

Example fix

// before
CREATE MATERIALIZED VIEW sales.daily_mv AS SELECT ...; -- ALREADY_EXISTS
// after
DROP MATERIALIZED VIEW IF EXISTS sales.daily_mv;
CREATE MATERIALIZED VIEW sales.daily_mv AS SELECT ...;
Defensive patterns

Strategy: try-catch

Validate before calling

-- Check for an existing object with the target name first:
SHOW TABLES FROM sales LIKE 'daily_mv';

Try / catch

try {
    stmt.execute("CREATE MATERIALIZED VIEW sales.daily_mv AS SELECT ...");
} catch (SQLException e) {
    if (e.getMessage() != null && e.getMessage().contains("already exists")) {
        // skip (idempotent), or DROP ... IF EXISTS then recreate
    } else { throw e; }
}

Prevention

When it happens

Trigger: Creating a materialized view whose name collides with an existing table or materialized view in the same schema; two concurrent CREATE MATERIALIZED VIEW statements racing on the same name.

Common situations: Name collision between a plain table and a materialized view; re-running a deployment script that creates MVs idempotently-naively; concurrent orchestration jobs creating the same MV.

Related errors


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