pinpoint-apm/pinpoint · error · IllegalArgumentException
Cannot add an existing column family :
Error message
Cannot add an existing column family :
What it means
Thrown by TableCommand.applyColumnFamilyChanges when a schema change requests CREATE of a column family that already exists in the target table's descriptor. The library refuses to re-create an existing family instead of silently overwriting its configuration. This is a fail-fast guard for non-idempotent column family additions.
Source
Thrown at hbase/hbase-schema/src/main/java/com/navercorp/pinpoint/hbase/schema/core/command/TableCommand.java:100
}
TableConfiguration.Durability durability = tableConfiguration.getDurability();
if (durability != null) {
builder.setDurability(Durability.valueOf(durability.name()));
}
}
void applyColumnFamilyChanges(List<ColumnFamilyChange> columnFamilyChanges) {
if (CollectionUtils.isEmpty(columnFamilyChanges)) {
return;
}
TableDescriptor tableDescriptor = builder.build();
for (ColumnFamilyChange columnFamilyChange : columnFamilyChanges) {
ChangeType changeType = columnFamilyChange.getType();
if (changeType == ChangeType.CREATE) {
ColumnFamilyDescriptor family = newColumnDescriptor(columnFamilyChange);
if (tableDescriptor.hasColumnFamily(family.getName())) {
throw new IllegalArgumentException("Cannot add an existing column family : " + tableDescriptor.getTableName().getNameAsString());
}
builder.setColumnFamily(family);
} else {
throw new UnsupportedOperationException("Unknown change type : " + changeType);
}
}
}
private ColumnFamilyDescriptor newColumnDescriptor(ColumnFamilyChange columnFamilyChange) {
byte[] name = BytesUtils.toBytes(columnFamilyChange.getName());
ColumnFamilyDescriptorBuilder builder = ColumnFamilyDescriptorBuilder.newBuilder(name);
ColumnFamilyConfiguration columnFamilyConfiguration = columnFamilyChange.getColumnFamilyConfiguration();
Boolean blockCacheEnabled = columnFamilyConfiguration.getBlockCacheEnabled();
if (blockCacheEnabled != null) {
builder.setBlockCacheEnabled(blockCacheEnabled);
}
Integer replicationScope = columnFamilyConfiguration.getReplicationScope();View on GitHub (pinned to 744c3d3075)
Solutions
- Remove the duplicate CREATE column family entry from the change set, or skip the change set since the family already exists
- Express the change as an update/modify of the existing column family instead of CREATE
- Check current table state (Admin.getDescriptor) before applying and filter out families that already exist
- If the previous run failed midway, verify which changes were applied and start from the correct change set id
Example fix
// before
new ColumnFamilyChange("TestAgent", ChangeType.CREATE, config) // family already on table
// after
if (!admin.getDescriptor(tableName).hasColumnFamily(Bytes.toBytes("TestAgent"))) {
applyChange(new ColumnFamilyChange("TestAgent", ChangeType.CREATE, config));
} Defensive patterns
Strategy: validation
Validate before calling
HColumnDescriptor existing = descriptor.getFamily(Bytes.toBytes(familyName));
if (existing != null) {
throw new IllegalStateException("Column family already exists: " + familyName);
} Type guard
boolean canCreateFamily(TableDescriptor td, String name) {
return !td.hasColumnFamily(Bytes.toBytes(name));
} Try / catch
try {
command.applyTableChange(change);
} catch (IllegalArgumentException e) {
if (e.getMessage().startsWith("Cannot add an existing column family")) {
// skip or convert to update
} else {
throw e;
}
} Prevention
- Check Admin.getDescriptor(...).hasColumnFamily before issuing CREATE changes
- Keep applied change sets tracked so they are not re-run
- Use a modify operation for configuration updates to existing families
When it happens
Trigger: Calling applyTableChange/applyColumnFamilyChanges with a ColumnFamilyChange of ChangeType.CREATE whose family name is already present in tableDescriptor (tableDescriptor.hasColumnFamily(family.getName()) is true).
Common situations: Re-running a change set that was already partially applied; two change sets both adding the same family name to a table; editing an existing column family's config but expressing it as CREATE instead of a modify operation; stale local schema state vs the actual HBase table.
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
- splitKeys must not be empty
- numRegions must be greater than 1
- Cyclic include detected for :
- Duplicate changeSet found. Id:
- not found
AI-assisted analysis of pinpoint-apm/pinpoint@744c3d3075 (2026-09-07).
Data as JSON: /api/errors/8c3089be94cd078c.
Report an issue: GitHub.