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

  1. Run the greenDAO generator (DaoGenerator) to regenerate all entity and Dao classes from your schema definition
  2. Clean and rebuild the project so stale generated classes are replaced
  3. 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
  4. 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

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


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)