prestodb/presto · error · PrestoException

ALREADY_EXISTS

ALREADY_EXISTS

Error message

ALREADY_EXISTS: SQLException

What it means

PostgreSqlClient.createTable wraps SQLExceptions from the underlying CREATE TABLE statement. When PostgreSQL reports SQLSTATE 42P07 (duplicate_table), it is translated into a PrestoException with function code ALREADY_EXISTS so callers can distinguish 'table already exists' from other JDBC failures.

Source

Thrown at presto-postgresql/src/main/java/com/facebook/presto/plugin/postgresql/PostgreSqlClient.java:178

        else if (typeHandle.getJdbcTypeName().equals("uuid")) {
            return Optional.of(uuidReadMapping());
        }
        else if (typeName.equalsIgnoreCase(GEOMETRY) || typeName.equalsIgnoreCase(SPHERICAL_GEOGRAPHY)) {
            return Optional.of(geometryReadMapping());
        }
        return super.toPrestoType(session, typeHandle);
    }

    @Override
    public void createTable(ConnectorSession session, ConnectorTableMetadata tableMetadata)
    {
        try {
            createTable(tableMetadata, session, tableMetadata.getTable().getTableName());
        }
        catch (SQLException e) {
            if (DUPLICATE_TABLE_SQLSTATE.equals(e.getSQLState())) {
                throw new PrestoException(ALREADY_EXISTS, e);
            }
            throw new PrestoException(JDBC_ERROR, e);
        }
    }

    @Override
    protected void renameTable(JdbcIdentity identity, String catalogName, SchemaTableName oldTable, SchemaTableName newTable)
    {
        // PostgreSQL does not allow qualifying the target of a rename
        try (Connection connection = connectionFactory.openConnection(identity)) {
            String sql = format(
                    "ALTER TABLE %s RENAME TO %s",
                    quoted(catalogName, oldTable.getSchemaName(), oldTable.getTableName()),
                    quoted(newTable.getTableName()));
            execute(connection, sql);
        }
        catch (SQLException e) {
            throw new PrestoException(JDBC_ERROR, e);

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Drop the existing table first if it is stale: DROP TABLE <schema>.<table> (in PostgreSQL or via the connector)
  2. Use CREATE TABLE IF NOT EXISTS at the caller level / check existence via SHOW TABLES before creating
  3. Serialize DDL so concurrent workers don't race to create the same table
  4. If the name collision is unintentional, choose a different target table name

Example fix

// before
CREATE TABLE catalog.schema.my_table (...);
// after
DROP TABLE IF EXISTS catalog.schema.my_table;
CREATE TABLE catalog.schema.my_table (...);
Defensive patterns

Strategy: try-catch

Validate before calling

sql
SELECT 1 FROM information_schema.tables
WHERE table_schema = '<schema>' AND table_name = '<table>';

Try / catch

java
try {
    client.createTable(session, tableMetadata);
} catch (PrestoException e) {
    if (e.getErrorCode() == ALREADY_EXISTS.toErrorCode().getCode()) {
        // table already exists — treat as no-op or drop and recreate
    } else {
        throw e;
    }
}

Prevention

When it happens

Trigger: Executing CREATE TABLE against PostgreSQL when a table with the same schema-qualified name already exists in the backing database (DUPLICATE_TABLE_SQLSTATE = 42P07).

Common situations: CREATE TABLE IF NOT EXISTS semantics racing with another query/connector writing the same table, retrying a DDL statement that partially succeeded, two Presto workers executing the same metadata DDL concurrently, or a leftover table from a previous failed run.

Related errors


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