{"record":{"id":"988edb0644bf9bc3","repo":"prestodb/presto","slug":"hive-concurrent-modification-detected","errorCode":"HIVE_CONCURRENT_MODIFICATION_DETECTED","errorMessage":"Table format changed during insert","messagePattern":"Table format changed during insert","errorType":"error_code","errorClass":"PrestoException","httpStatus":null,"severity":"error","filePath":"presto-hive/src/main/java/com/facebook/presto/hive/HiveMetadata.java","lineNumber":2218,"sourceCode":"    {\n        return finishInsertInternal(session, insertHandle, fragments, computedStatistics);\n    }\n\n    private Optional<ConnectorOutputMetadata> finishInsertInternal(ConnectorSession session, ConnectorInsertTableHandle insertHandle, Collection<Slice> fragments, Collection<ComputedStatistics> computedStatistics)\n    {\n        HiveInsertTableHandle handle = (HiveInsertTableHandle) insertHandle;\n\n        List<PartitionUpdate> partitionUpdates = getPartitionUpdates(session, fragments);\n\n        HiveStorageFormat tableStorageFormat = handle.getTableStorageFormat();\n        partitionUpdates = PartitionUpdate.mergePartitionUpdates(partitionUpdates);\n\n        MetastoreContext metastoreContext = getMetastoreContext(session);\n\n        Table table = metastore.getTable(metastoreContext, handle.getSchemaName(), handle.getTableName())\n                .orElseThrow(() -> new TableNotFoundException(handle.getSchemaTableName()));\n        if (!table.getStorage().getStorageFormat().getInputFormat().equals(tableStorageFormat.getInputFormat()) && isRespectTableFormat(session)) {\n            throw new PrestoException(HIVE_CONCURRENT_MODIFICATION_DETECTED, \"Table format changed during insert\");\n        }\n\n        if (handle.getBucketProperty().isPresent() && isCreateEmptyBucketFiles(session)) {\n            List<PartitionUpdate> partitionUpdatesForMissingBuckets = computePartitionUpdatesForMissingBuckets(\n                    session,\n                    handle,\n                    table,\n                    partitionUpdates);\n            // replace partitionUpdates before creating the zero-row files so that those files will be cleaned up if we end up rollback\n            partitionUpdates = PartitionUpdate.mergePartitionUpdates(concat(partitionUpdates, partitionUpdatesForMissingBuckets));\n            HdfsContext hdfsContext = new HdfsContext(session, table.getDatabaseName(), table.getTableName(), table.getStorage().getLocation(), false);\n            for (PartitionUpdate partitionUpdate : partitionUpdatesForMissingBuckets) {\n                Optional<Partition> partition = table.getPartitionColumns().isEmpty() ? Optional.empty() :\n                        Optional.of(partitionObjectBuilder.buildPartitionObject(\n                                session,\n                                table,\n                                partitionUpdate,\n                                prestoVersion,","sourceCodeStart":2200,"sourceCodeEnd":2236,"githubUrl":"https://github.com/prestodb/presto/blob/55bb57d202de3b926896fa966c2c4a44c779634e/presto-hive/src/main/java/com/facebook/presto/hive/HiveMetadata.java#L2200-L2236","documentation":"Presto detected that the target table's storage format (input format) changed between the moment the INSERT statement began and when metadata was being finalized. Because the session honors the table format (respect-table-format), the earlier-captured format is stale, and continuing could write files in the wrong format. Presto throws HIVE_CONCURRENT_MODIFICATION_DETECTED to abort safely.","triggerScenarios":"A concurrent ALTER TABLE ... SET FILEFORMAT / SET TABLE PROPERTIES (storage format change) or a table replacement happened while an INSERT into that table was in progress, checked in finishInsert when respect_table_format is enabled.","commonSituations":"Migration scripts running format conversions (e.g. TextFile to ORC) concurrently with ETL INSERT jobs on the same table.","solutions":["Rerun the INSERT after the concurrent ALTER completes; the retry will see the new format","Coordinate format-change DDL so it runs outside ETL windows (job scheduling/mutual exclusion)","If intentional and acceptable, set session respect_table_format=false so writes use the session format (verify this is actually desired)"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// Before finalizing: re-read the table and compare input formats\nTable current = metastore.getTable(ctx, schema, table).orElseThrow();\nif (!current.getStorage().getStorageFormat().getInputFormat()\n        .equals(expectedFormat.getInputFormat())) {\n    throw new IllegalStateException(\"Format changed concurrently; rerun insert\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    session.execute(\"INSERT INTO target SELECT ...\");\n} catch (PrestoException e) {\n    if (e.getErrorCode().getCode() == HIVE_CONCURRENT_MODIFICATION_DETECTED.getCode()) {\n        // safe to retry: re-plan sees the new table format\n    } else { throw e; }\n}","preventionTips":["Serialize table-format DDL (ALTER ... SET FILEFORMAT) with ETL jobs via scheduler locks","Run format migrations in maintenance windows","Monitor for HIVE_CONCURRENT_MODIFICATION_DETECTED to detect pipeline collisions"],"tags":["hive","concurrent-modification","storage-format","insert"],"backgroundTag":"concurrent-modification-detected","analyzedSha":"55bb57d202de3b926896fa966c2c4a44c779634e","analyzedAt":"2026-09-04T12:50:26.162Z","contentChangedAt":"2026-09-04T12:50:26.162Z","schemaVersion":2},"datasetVersion":"2026-09-11T21:17:09.523Z"}