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
- Choose a different materialized view name or drop/rename the existing object first
- Check existence with SHOW TABLES / system.metadata before creating, and skip if present
- Use CREATE OR REPLACE semantics if available, or DROP MATERIALIZED VIEW before recreate
- 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
- Guard deployment scripts with DROP ... IF EXISTS or existence checks
- Avoid reusing plain-table names for materialized views
- Serialize MV creation in orchestration to prevent races
- Adopt deterministic naming conventions per environment
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
- NOT_FOUND
- INVALID_TABLE_PROPERTY
- INVALID_MATERIALIZED_VIEW_PROPERTY
- NOT_SUPPORTED
- INVALID_TABLE_PROPERTY
AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04).
Data as JSON: /api/errors/bcd3d0eecef687e8.
Report an issue: GitHub.