prestodb/presto · error · ViewAlreadyExistsException

View already exists

Error message

View already exists

What it means

Mapped from TableAlreadyExistsException when CREATE VIEW (or CREATE OR REPLACE VIEW) finds an object already stored under the view name. If the existing table is not a Presto view (e.g. a real table), or the statement was plain CREATE VIEW without OR REPLACE, creation is rejected. Presto translates the metastore conflict into ViewAlreadyExistsException.

Source

Thrown at presto-hive/src/main/java/com/facebook/presto/hive/HiveMetadata.java:2476

    @Override
    public void createView(ConnectorSession session, ConnectorTableMetadata viewMetadata, String viewData, boolean replace)
    {
        MetastoreContext metastoreContext = getMetastoreContext(session);
        SchemaTableName viewName = viewMetadata.getTable();
        Table table = createTableObjectForViewCreation(
                session,
                viewMetadata,
                createViewProperties(session, prestoVersion),
                typeTranslator,
                metastoreContext,
                encodeViewData(viewData));
        PrincipalPrivileges principalPrivileges = buildInitialPrivilegeSet(session.getUser());

        Optional<Table> existing = metastore.getTable(metastoreContext, viewName.getSchemaName(), viewName.getTableName());
        if (existing.isPresent()) {
            if (!replace || !MetastoreUtil.isPrestoView(existing.get())) {
                throw new ViewAlreadyExistsException(viewName);
            }

            metastore.replaceView(metastoreContext, viewName.getSchemaName(), viewName.getTableName(), table, principalPrivileges);
            return;
        }

        try {
            metastore.createTable(session, table, principalPrivileges, Optional.empty(), false, new PartitionStatistics(createEmptyStatistics(), ImmutableMap.of()), emptyList());
        }
        catch (TableAlreadyExistsException e) {
            throw new ViewAlreadyExistsException(e.getTableName());
        }
    }

    @Override
    public void dropView(ConnectorSession session, SchemaTableName viewName)
    {
        ConnectorViewDefinition view = getViews(session, viewName.toSchemaTablePrefix()).get(viewName);

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Use CREATE OR REPLACE VIEW — works only if the existing object is a Presto view
  2. If a real Hive table occupies the name, DROP TABLE <name> first, then create the view
  3. Use CREATE VIEW IF NOT EXISTS to skip when it already exists
  4. Pick a different view name

Example fix

-- before
CREATE VIEW analytics.daily_revenue AS SELECT ...;
-- after
CREATE OR REPLACE VIEW analytics.daily_revenue AS SELECT ...;
-- or defensively:
CREATE VIEW IF NOT EXISTS analytics.daily_revenue AS SELECT ...;
Defensive patterns

Strategy: validation

Validate before calling

-- guard in deploy tooling
SELECT true FROM system.metadata.tables
WHERE schema_name = 'analytics' AND table_name = 'daily_revenue';
-- if true: use CREATE OR REPLACE VIEW or drop first

Try / catch

try {
    createView(ddl);
} catch (ViewAlreadyExistsException e) {
    // deliberate idempotency: verify then replace
    run("CREATE OR REPLACE VIEW " + viewName + " AS " + sql);
}

Prevention

When it happens

Trigger: CREATE VIEW on an existing name; CREATE OR REPLACE VIEW where the existing object is a native Hive table (not isPrestoView); metastore already contains a table/view with that schema.table name.

Common situations: Re-running a deployment script that creates views idempotently without IF NOT EXISTS; a stale Hive table occupying the intended view name; switching a name from table to view without dropping it first.

Related errors


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