apache/beam · error · SqlUtil.newContextException
Table ' ' already exists
Error message
Table '%s' already exists
What it means
Thrown when CREATE EXTERNAL TABLE targets a table name that already exists in the Calcite schema and the statement lacks IF NOT EXISTS. Beam's SQL DDL parser checks pair.left.plus().getTable(pair.right) before building the table and raises a parse-context error via Calcite's RESOURCE.tableExists. It is a user-facing duplicate-definition guard, not an internal failure.
Solutions
- Add IF NOT EXISTS to the CREATE EXTERNAL TABLE statement
- Use a different table name
- Explicitly DROP EXTERNAL TABLE the existing table first (or use CREATE OR REPLACE semantics if supported)
- Inspect existing tables with schema metadata queries before running DDL
Example fix
// before CREATE EXTERNAL TABLE orders (...) TYPE 'csv' LOCATION '/tmp/orders'; // after CREATE EXTERNAL TABLE IF NOT EXISTS orders (...) TYPE 'csv' LOCATION '/tmp/orders';
Defensive patterns
Strategy: validation
Validate before calling
// Run before DDL
// SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'orders';
boolean exists = schema.getTableNames().stream().anyMatch(n -> n.equalsIgnoreCase("orders"));
if (exists) { /* skip create or drop first */ } Prevention
- Always use IF NOT EXISTS in idempotent bootstrap scripts
- Drop-then-create explicitly when replacement is intended
- Keep DDL scripts run-once or track applied migrations
When it happens
Trigger: Executing `CREATE EXTERNAL TABLE <name> ...` where a table (or external table) with the same simple name is already registered in the target schema and IF NOT EXISTS was not specified.
Common situations: Re-running an idempotent DDL script or pipeline bootstrap without IF NOT EXISTS; two jobs/DDL sessions creating the same external table name; migrating scripts from engines that silently replace tables.
Understand the failure class
Background: "already exists" / EEXIST / FileAlreadyExistsException: what the 'file already exists' error means and how to fix it — this error's family across 37 libraries.
Related errors
- Attempting to alter catalog
- Attempting to create a table with unexpected Calcite Schema…
- Attempting to create catalog
- Attempting to create database
- Attempting to drop a catalog
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/44ae8eda9e0918de.
Report an issue: GitHub.
Appendix: source
Thrown at sdks/java/extensions/sql/src/main/java/org/apache/beam/sdk/extensions/sql/impl/parser/SqlCreateExternalTable.java:148
}
if (location != null) {
writer.keyword("LOCATION");
location.unparse(writer, 0, 0);
}
if (tblProperties != null) {
writer.keyword("TBLPROPERTIES");
tblProperties.unparse(writer, 0, 0);
}
}
@Override
public void execute(CalcitePrepare.Context context) {
final Pair<CalciteSchema, String> pair = SqlDdlNodes.schema(context, true, name);
if (pair.left.plus().getTable(pair.right) != null) {
// Table exists.
if (!ifNotExists) {
// They did not specify IF NOT EXISTS, so give error.
throw SqlUtil.newContextException(
name.getParserPosition(), RESOURCE.tableExists(pair.right));
}
return;
}
Schema schema = pair.left.schema;
BeamCalciteSchema beamCalciteSchema;
if (schema instanceof CatalogManagerSchema) {
TableName pathOverride = TableName.create(name.toString());
CatalogManagerSchema catalogManagerSchema = (CatalogManagerSchema) schema;
catalogManagerSchema.maybeRegisterProvider(pathOverride, SqlDdlNodes.getString(type));
CatalogSchema catalogSchema = catalogManagerSchema.getCatalogSchema(pathOverride);
beamCalciteSchema = catalogSchema.getDatabaseSchema(pathOverride);
} else if (schema instanceof BeamCalciteSchema) {
beamCalciteSchema = (BeamCalciteSchema) schema;
} else {View on GitHub (pinned to 12126d8942)