greenrobot/greenDAO · critical · DaoException
Duplicate property ordinals
Error message
Duplicate property ordinals
What it means
During DAO configuration, greenDAO collects entity properties from generated classes into a list and places each into an array indexed by its `ordinal`. If two Property instances share the same ordinal value, the slot would be overwritten, so a DaoException is thrown. Ordinals must be unique because they map to bind-parameter positions in generated SQL.
Solutions
- Run the greenDAO generator (DaoGenerator) to regenerate all entity and Dao classes from your schema definition
- Clean and rebuild the project so stale generated classes are replaced
- Inspect the entity class for two static Property fields with the same ordinal value and correct the schema so each column gets a unique ordinal
- Ensure no manually added Property constants duplicate generated ones
Example fix
// before (in entity class) public static final Property Name = new Property(0, String.class, "name", false, "NAME"); public static final Property Age = new Property(0, Long.class, "age", false, "AGE"); // after public static final Property Name = new Property(0, String.class, "name", false, "NAME"); public static final Property Age = new Property(1, Long.class, "age", false, "AGE");
Defensive patterns
Strategy: validation
Validate before calling
long distinctOrdinals = allProperties.stream().mapToInt(p -> p.ordinal).distinct().count();
if (distinctOrdinals != allProperties.size()) throw new IllegalStateException("Duplicate Property ordinals in entity"); Try / catch
try {
dao = new MyDao(db, config);
} catch (DaoException e) {
if (e.getMessage().contains("Duplicate property ordinals")) {
// regenerate entity/Dao classes before app start
}
} Prevention
- Never hand-edit generated *Dao.java or entity Property constants
- Always regenerate via DaoGenerator after schema changes
- Add a unit test asserting unique ordinals per entity
- Clean builds when generated code seems out of sync
When it happens
Trigger: A generated entity class (or custom static Property fields) declares two properties with the same ordinal value, typically due to hand-edited generated code, stale generated files after schema edits, or duplicate column definitions.
Common situations: Running an outdated code generator after adding columns; manually editing *Dao.java files; copy-pasting Property constants between entities without changing ordinals; partial/corrupt build artifacts from annotation processing.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- Property already defined:
- Property does not exist in
- AUTOINCREMENT is only available to primary key properties…
- No DAO registered for
- Could not init DAOConfig
AI-assisted analysis of greenrobot/greenDAO@0bbb338e17 (2026-09-08).
Data as JSON: /api/errors/316a402475432592.
Report an issue: GitHub.
Appendix: source
Thrown at DaoCore/src/main/java/org/greenrobot/greendao/internal/DaoConfig.java:118
Class<?> propertiesClass = Class.forName(daoClass.getName() + "$Properties");
Field[] fields = propertiesClass.getDeclaredFields();
ArrayList<Property> propertyList = new ArrayList<Property>();
final int modifierMask = Modifier.STATIC | Modifier.PUBLIC;
for (Field field : fields) {
// There might be other fields introduced by some tools, just ignore them (see issue #28)
if ((field.getModifiers() & modifierMask) == modifierMask) {
Object fieldValue = field.get(null);
if (fieldValue instanceof Property) {
propertyList.add((Property) fieldValue);
}
}
}
Property[] properties = new Property[propertyList.size()];
for (Property property : propertyList) {
if (properties[property.ordinal] != null) {
throw new DaoException("Duplicate property ordinals");
}
properties[property.ordinal] = property;
}
return properties;
}
/** Does not copy identity scope. */
public DaoConfig(DaoConfig source) {
db = source.db;
tablename = source.tablename;
properties = source.properties;
allColumns = source.allColumns;
pkColumns = source.pkColumns;
nonPkColumns = source.nonPkColumns;
pkProperty = source.pkProperty;
statements = source.statements;
keyIsNumeric = source.keyIsNumeric;
}View on GitHub (pinned to 0bbb338e17)