greenrobot/greenDAO · error · RuntimeException
Source entity has no primary key, but we need it for
Error message
Source entity has no primary key, but we need it for
What it means
ToMany.init2ndPass() requires the source entity of a to-many relation to have a primary key, because the generated join query filters target rows by the source entity's PK columns. When sourceProperties was not explicitly set and the source entity has no PK properties, the generator aborts with this RuntimeException naming the relation.
Solutions
- Add a primary key to the source entity (e.g. entity.addIdProperty().primaryKey())
- Explicitly set source properties for the relation via toMany.setSourceProperties(...) matching target properties
- If the source table genuinely has no PK, add one (even a composite or synthetic column) before generating
- Verify entity.getPropertiesPk() returns the intended PK by checking the entity definition
Example fix
// before
Entity user = schema.addEntity("User"); // no PK
Entity note = schema.addEntity("Note");
user.addToMany(note, note.getUserId());
// after
Entity user = schema.addEntity("User");
user.addIdProperty().primaryKey();
user.addToMany(note, note.getUserId()); Defensive patterns
Strategy: validation
Validate before calling
if (sourceEntity.getPropertiesPk().isEmpty()) throw new IllegalStateException("Source entity needs a PK before addToMany"); Type guard
function hasPk(entity) { return entity != null && entity.getPkProperty() != null; } Try / catch
try { schema.generate(); } catch (RuntimeException e) { if (e.getMessage().startsWith("Source entity has no primary key")) { fixSchemaDefinition(e.getMessage()); } else { throw e; } } Prevention
- Always call addIdProperty().primaryKey() on entities used as ToMany sources
- Validate all entities have PKs before running the generator
- Review legacy table definitions for missing PKs
When it happens
Trigger: Creating a ToMany relation (entity.addToMany) where the source entity defines no primary key and no explicit sourceProperties are supplied via setSourceProperties/setOrderBy.
Common situations: Generating an entity from a legacy table without a primary key; forgetting .primaryKey() on the source entity's id property; schema copied from a NoSQL design into greenDAO.
Understand the failure class
Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.
Related errors
- Source properties do not match target properties:
- Property type uninitialized
- Source entity has no primary key, but we need it for
- Target entity has no primary key, but we need it for
- ( ) does not have a single-column primary key
AI-assisted analysis of greenrobot/greenDAO@0bbb338e17 (2026-09-08).
Data as JSON: /api/errors/8abdfb0399dccab2.
Report an issue: GitHub.
Appendix: source
Thrown at DaoGenerator/src/org/greenrobot/greendao/generator/ToMany.java:53
public Property[] getSourceProperties() {
return sourceProperties;
}
public void setSourceProperties(Property[] sourceProperties) {
this.sourceProperties = sourceProperties;
}
public Property[] getTargetProperties() {
return targetProperties;
}
void init2ndPass() {
super.init2ndPass();
if (sourceProperties == null) {
List<Property> pks = sourceEntity.getPropertiesPk();
if (pks.isEmpty()) {
throw new RuntimeException("Source entity has no primary key, but we need it for " + this);
}
sourceProperties = new Property[pks.size()];
sourceProperties = pks.toArray(sourceProperties);
}
int count = sourceProperties.length;
if (count != targetProperties.length) {
throw new RuntimeException("Source properties do not match target properties: " + this);
}
for (int i = 0; i < count; i++) {
Property sourceProperty = sourceProperties[i];
Property targetProperty = targetProperties[i];
PropertyType sourceType = sourceProperty.getPropertyType();
PropertyType targetType = targetProperty.getPropertyType();
if (sourceType == null || targetType == null) {
throw new RuntimeException("Property type uninitialized");
}View on GitHub (pinned to 0bbb338e17)