prestodb/presto · error · SemanticException
MISSING_COLUMN
MISSING_COLUMN
Error message
Column '%s' does not exist
What it means
After access-control checks, DropColumnTask looks up the column in metadata.getColumnHandles(session, tableHandle). A null/absent handle means the column does not exist on the table; without IF COLUMN EXISTS (isColumnExists), it throws SemanticException(MISSING_COLUMN) naming the column.
Source
Thrown at presto-main-base/src/main/java/com/facebook/presto/execution/DropColumnTask.java:79
Optional<MaterializedViewDefinition> optionalMaterializedView = metadata.getMetadataResolver(session).getMaterializedView(tableName);
if (optionalMaterializedView.isPresent()) {
if (!statement.isTableExists()) {
throw new SemanticException(NOT_SUPPORTED, statement, "'%s' is a materialized view, and drop column is not supported", tableName);
}
return immediateFuture(null);
}
TableHandle tableHandle = tableHandleOptional.get();
Identifier columnIdentifier = statement.getColumn();
String column = metadata.normalizeIdentifier(session, tableName.getCatalogName(), columnIdentifier.getValue());
accessControl.checkCanDropColumn(session.getRequiredTransactionId(), session.getIdentity(), session.getAccessControlContext(), tableName);
ColumnHandle columnHandle = metadata.getColumnHandles(session, tableHandle).get(column);
if (columnHandle == null) {
if (!statement.isColumnExists()) {
throw new SemanticException(MISSING_COLUMN, statement, "Column '%s' does not exist", column);
}
return immediateFuture(null);
}
if (metadata.getColumnMetadata(session, tableHandle, columnHandle).isHidden()) {
throw new SemanticException(NOT_SUPPORTED, statement, "Cannot drop hidden column");
}
if (metadata.getTableMetadata(session, tableHandle).getColumns().stream()
.filter(info -> !info.isHidden()).count() <= 1) {
throw new SemanticException(NOT_SUPPORTED, statement, "Cannot drop the only column in a table");
}
metadata.dropColumn(session, tableHandle, columnHandle);
return immediateFuture(null);
}
}View on GitHub (pinned to 55bb57d202)
Solutions
- Check the exact column name with SHOW COLUMNS FROM <table> and correct casing/spelling (quote the identifier if needed).
- Add IF EXISTS for the column to make repeated migrations idempotent.
- If the column was already dropped, skip the statement in your migration logic.
Example fix
// before ALTER TABLE hive.default.events DROP COLUMN TempFlag; -- actual name: tempflag // after ALTER TABLE hive.default.events DROP COLUMN IF EXISTS tempflag;
Defensive patterns
Strategy: validation
Validate before calling
-- Verify the column exists before DROP COLUMN SELECT column_name FROM information_schema.columns WHERE table_catalog='hive' AND table_schema='default' AND table_name='events' AND lower(column_name) = 'tempflag';
Type guard
function columnExists(session, qname, col) {
return session.execute(
'SELECT count(*) FROM information_schema.columns WHERE table_catalog=? AND table_schema=? AND table_name=? AND lower(column_name)=lower(?)',
[qname.catalog, qname.schema, qname.table, col]) > 0;
} Try / catch
try {
session.execute(`ALTER TABLE ${t} DROP COLUMN IF EXISTS ${c}`);
} catch (e) {
if (/Column '.*' does not exist/.test(e.message)) {
log.info(`Column ${c} already absent; continuing migration`);
return;
}
throw e;
} Prevention
- Run SHOW COLUMNS FROM <table> before every DROP COLUMN in migrations.
- Make column drops idempotent with IF EXISTS.
- Quote identifiers to control case sensitivity and compare case-insensitively when checking.
When it happens
Trigger: ALTER TABLE <table> DROP COLUMN <col> where <col> is not among the table's column handles and the statement did not use IF EXISTS for the column.
Common situations: Column already dropped in a prior run of a migration script; case-sensitivity mismatch (quoted vs unquoted identifiers); column renamed upstream; dropping a column that only exists in a view definition, not the table.
Related errors
AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04).
Data as JSON: /api/errors/8aef01cc16acc4b5.
Report an issue: GitHub.