greenrobot/greenDAO · error · RuntimeException
Source properties do not match target properties:
Error message
Source properties do not match target properties:
What it means
ToMany.init2ndPass() checks that the number of source join properties equals the number of target join properties; the generated JOIN/IN clause pairs them positionally. When sourceProperties.length != targetProperties.length the relation is malformed and the generator throws this RuntimeException.
Solutions
- Make the source and target property lists the same length, pairing columns positionally
- Use the simple addToMany(targetEntity, targetProperty) overload for single-column relations
- For composite keys, pass matching counts on both sides (e.g. 2 source PKs and 2 target FKs)
- Print both lists during generation setup to confirm the pairing
Example fix
// before toMany.setSourceProperties(srcA, srcB); // 2 sources toMany.setTargetProperties(tgtA); // 1 target -> mismatch // after toMany.setTargetProperties(tgtA, tgtB); // 2 targets, paired positionally
Defensive patterns
Strategy: validation
Validate before calling
if (sourceProps.size() != targetProps.size()) throw new IllegalArgumentException("ToMany source/target property counts differ"); Type guard
function countsMatch(src, tgt) { return Array.isArray(src) && Array.isArray(tgt) && src.length === tgt.length; } Try / catch
try { schema.generate(); } catch (RuntimeException e) { if (e.getMessage().startsWith("Source properties do not match target")) { comparePropertyLists(); } else { throw e; } } Prevention
- Use the simple single-property addToMany overload unless composite keys are required
- Keep composite source/target lists in adjacent code so lengths are visually checkable
- Add a unit test asserting list lengths in your generator setup
When it happens
Trigger: Calling setSourceProperties/setTargetProperties (or a constructor variant) on a ToMany with lists of different lengths, e.g. two source columns against one target column.
Common situations: Composite-key relation where only one side's columns were specified; typo passing the same list twice with different filters; refactoring one entity's key columns without updating the other.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Source entity has no primary key, but we need it for
- Property type uninitialized
- Type is already non-primitive
- No mapping for
- Source entity has no primary key, but we need it for
AI-assisted analysis of greenrobot/greenDAO@0bbb338e17 (2026-09-08).
Data as JSON: /api/errors/78e03b64540abbf9.
Report an issue: GitHub.
Appendix: source
Thrown at DaoGenerator/src/org/greenrobot/greendao/generator/ToMany.java:60
}
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");
}
if (sourceType != targetType) {
System.err.println("Warning to-one property type does not match target key type: " + this);
}
}
}
void init3rdPass() {View on GitHub (pinned to 0bbb338e17)