{"record":{"id":"a38425b9b126c235","repo":"prestodb/presto","slug":"hive-partition-read-only","errorCode":"HIVE_PARTITION_READ_ONLY","errorMessage":"Cannot insert into an existing partition of Hive table: ","messagePattern":"Cannot insert into an existing partition of Hive table: ","errorType":"error_code","errorClass":"PrestoException","httpStatus":null,"severity":"error","filePath":"presto-hive/src/main/java/com/facebook/presto/hive/HiveMetadata.java","lineNumber":2336,"sourceCode":"                getManifestSizeInBytes(session, partitionUpdate, extraPartitionMetadata).ifPresent(hivePartitionStats::addManifestSizeInBytes);\n\n                boolean isExistingPartition = existingPartitions.containsKey(partitionUpdate.getName());\n                Optional<Partition> existingPartition = Optional.empty();\n                if (isExistingPartition) {\n                    // Overwriting an existing partition\n                    if (partitionUpdate.getUpdateMode() == OVERWRITE) {\n                        existingPartition = existingPartitions.get(partitionUpdate.getName());\n                        if (handle.getLocationHandle().getWriteMode() == DIRECT_TO_TARGET_EXISTING_DIRECTORY) {\n                            // In this writeMode, the new files will be written to the same directory. Since this is\n                            // an overwrite operation, we must remove all the old files not written by current query.\n                            removeNonCurrentQueryFiles(session, partitionUpdate.getTargetPath());\n                        }\n                        else {\n                            metastore.dropPartition(session, handle.getSchemaName(), handle.getTableName(), handle.getLocationHandle().getTargetPath().toString(), extractPartitionValues(partitionUpdate.getName()));\n                        }\n                    }\n                    else {\n                        throw new PrestoException(HIVE_PARTITION_READ_ONLY, \"Cannot insert into an existing partition of Hive table: \" + partitionUpdate.getName());\n                    }\n                }\n                // insert into new partition or overwrite existing partition\n                Partition partition = partitionObjectBuilder.buildPartitionObject(\n                        session,\n                        table,\n                        partitionUpdate,\n                        prestoVersion,\n                        extraPartitionMetadata,\n                        existingPartition,\n                        Optional.empty());\n                if (!partition.getStorage().getStorageFormat().getInputFormat().equals(handle.getPartitionStorageFormat().getInputFormat()) && isRespectTableFormat(session)) {\n                    throw new PrestoException(HIVE_CONCURRENT_MODIFICATION_DETECTED, \"Partition format changed during insert\");\n                }\n\n                String partitionName = partitionUpdate.getName();\n                List<String> partitionValues = partition.getValues();\n                List<Type> partitionTypes = partitionedBy.stream()","sourceCodeStart":2318,"sourceCodeEnd":2354,"githubUrl":"https://github.com/prestodb/presto/blob/55bb57d202de3b926896fa966c2c4a44c779634e/presto-hive/src/main/java/com/facebook/presto/hive/HiveMetadata.java#L2318-L2354","documentation":"The INSERT plan requires overwriting an existing partition, but the resolved update path for that partition is neither a supported overwrite (which would drop/recreate the partition) nor a new partition; the partition exists and Presto refuses to write into it. HIVE_PARTITION_READ_ONLY signals the existing partition is effectively read-only for this insert — typically because the behavior is ERROR or the write mode cannot drop the existing partition.","triggerScenarios":"INSERT with insert_existing_partitions_behavior=ERROR (default) hitting a partition that already exists; or a write mode (e.g. DIRECT_TO_TARGET_EXISTING_DIRECTORY precheck) that does not drop the partition, in the else-branch of the partition update loop in finishInsert.","commonSituations":"Repeated ETL runs re-inserting the same day's partition with the default ERROR behavior; backfills targeting partitions already loaded by another job.","solutions":["Set session insert_existing_partitions_behavior=OVERWRITE if the intent is to replace partition contents","Use INSERT with a filter excluding already-present partitions, or delete/drop the existing partition before inserting","If the partition is managed externally, load via a new partition (distinct value set) or use Hive to manage the overwrite"],"exampleFix":"// before\nINSERT INTO events PARTITION (ds='2026-09-01') SELECT ... ; -- partition exists, behavior=ERROR\n// after\nSET SESSION hive.insert_existing_partitions_behavior = 'OVERWRITE';\nINSERT INTO events PARTITION (ds='2026-09-01') SELECT ...;","handlingStrategy":"validation","validationCode":"// Before INSERT: check whether target partitions already exist\nList<String> existing = existingPartitionNames(metastore, ctx, schema, name, plannedPartitions);\nif (!existing.isEmpty()\n        && \"ERROR\".equals(session.getProperty(\"insert_existing_partitions_behavior\"))) {\n    throw new IllegalStateException(\"Existing partitions would block INSERT: \" + existing);\n}","typeGuard":null,"tryCatchPattern":"try {\n    session.execute(\"INSERT INTO events PARTITION (ds='...') SELECT ...\");\n} catch (PrestoException e) {\n    if (\"HIVE_PARTITION_READ_ONLY\".equals(e.getErrorCode().getName())) {\n        // drop the partition or set OVERWRITE behavior, then retry\n    } else { throw e; }\n}","preventionTips":["Pre-check existing partitions in ETL before inserting","Adopt a consistent insert_existing_partitions_behavior per pipeline","Use idempotent partition keys so reruns overwrite rather than collide"],"tags":["hive","insert","partition-read-only","overwrite"],"backgroundTag":"hive-partition-read-only","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"}