prestodb/presto · error · PrestoException

INVALID_PROCEDURE_ARGUMENT

INVALID_PROCEDURE_ARGUMENT

Error message

Table is not partitioned: 

What it means

INVALID_PROCEDURE_ARGUMENT from the system.sync_partition_metadata procedure when invoked on a table that has no partition columns. The procedure synchronizes partition metadata with files on HDFS, which is only meaningful for partitioned tables.

Source

Thrown at presto-hive/src/main/java/com/facebook/presto/hive/SyncPartitionMetadataProcedure.java:136

        SyncMode syncMode = toSyncMode(mode);
        SemiTransactionalHiveMetastore metastore = hiveMetadataFactory.get().getMetastore();
        SchemaTableName schemaTableName = new SchemaTableName(schemaName, tableName);

        MetastoreContext metastoreContext = new MetastoreContext(
                session.getIdentity(),
                session.getQueryId(),
                session.getClientInfo(),
                session.getClientTags(),
                session.getSource(),
                getMetastoreHeaders(session),
                isUserDefinedTypeEncodingEnabled(session),
                metastore.getColumnConverterProvider(),
                session.getWarningCollector(),
                session.getRuntimeStats());
        Table table = metastore.getTable(metastoreContext, schemaName, tableName)
                .orElseThrow(() -> new TableNotFoundException(schemaTableName));
        if (table.getPartitionColumns().isEmpty()) {
            throw new PrestoException(INVALID_PROCEDURE_ARGUMENT, "Table is not partitioned: " + schemaTableName);
        }
        Path tableLocation = new Path(table.getStorage().getLocation());
        HdfsContext context = new HdfsContext(session, schemaName, tableName, table.getStorage().getLocation(), false);

        Set<String> partitionsToAdd;
        Set<String> partitionsToDrop;

        try {
            FileSystem fileSystem = hdfsEnvironment.getFileSystem(context, tableLocation);
            List<PartitionNameWithVersion> partitionNamesInMetastore = metastore.getPartitionNames(metastoreContext, schemaName, tableName)
                    .orElseThrow(() -> new TableNotFoundException(schemaTableName));
            ImmutableList.Builder<String> partitionsInMetastore = new ImmutableList.Builder<>();
            for (List<PartitionNameWithVersion> batchPartitionNames : partition(partitionNamesInMetastore, GET_PARTITION_BY_NAMES_BATCH_SIZE)) {
                Map<String, Optional<Partition>> partitionsOptionalMap = metastore.getPartitionsByNames(metastoreContext, schemaName, tableName, batchPartitionNames);
                for (Map.Entry<String, Optional<Partition>> entry : partitionsOptionalMap.entrySet()) {
                    if (entry.getValue().isPresent()) {
                        partitionsInMetastore.add(tableLocation.toUri().relativize(new Path(entry.getValue().get().getStorage().getLocation()).toUri()).getPath());
                    }

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Confirm the table is partitioned: SHOW CREATE TABLE and check PARTITIONED BY; only run the procedure on partitioned tables
  2. Correct the schema/table name arguments if you meant a different table
  3. For unpartitioned tables there is nothing to sync; skip the call or drop/re-register the table if metadata is stale

Example fix

// before
CALL system.sync_partition_metadata('default', 'events_flat', 'FULL');
// after: verify first, then target a partitioned table
SHOW CREATE TABLE default.events_flat; -- confirm PARTITIONED BY
CALL system.sync_partition_metadata('default', 'events_partitioned', 'FULL');
Defensive patterns

Strategy: validation

Validate before calling

-- before calling the procedure
SHOW CREATE TABLE schema.table; -- must show PARTITIONED BY
-- or programmatic:
Table t = metastore.getTable(metastoreContext, schema, tableName)
    .orElseThrow(() -> new IllegalArgumentException("table missing"));
if (t.getPartitionColumns().isEmpty()) {
    throw new IllegalArgumentException("Not partitioned, skip sync: " + schema + "." + tableName);
}

Type guard

static boolean isPartitioned(Table table) {
    return table != null && !table.getPartitionColumns().isEmpty();
}

Try / catch

try {
    session.execute("CALL system.sync_partition_metadata('schema','table','FULL')");
} catch (PrestoException e) {
    if (StandardErrorCode.INVALID_PROCEDURE_ARGUMENT.toErrorCode().equals(e.getErrorCode())
            && e.getMessage().startsWith("Table is not partitioned:")) {
        // skip or correct the table name
    } else throw e;
}

Prevention

When it happens

Trigger: CALL system.sync_partition_metadata('schema','table','ADD'|'DROP'|'FULL') on a non-partitioned table: metastore.getTable succeeds but table.getPartitionColumns().isEmpty() is true in doSyncPartitionMetadata.

Common situations: Running the procedure against an unpartitioned table by mistake; passing wrong table name that resolves to a plain table; assuming all tables in a schema are partitioned in scripted maintenance jobs.

Related errors


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