OpenAPITools/openapi-generator · error · IllegalArgumentException
property %s in model %s uses generated storage name %s, whic
Error message
property %s in model %s uses generated storage name %s, which is an input name for property %s
What it means
When a property's public name differs from its storage name (i.e. it was remapped via --name-mapping), the generated model hides the storage attribute behind a public alias. The generator verifies that such a hidden storage name is never an accepted input name of a different property; otherwise input validation/aliasing would silently route one property's input into another property's storage. Violation throws this IllegalArgumentException.
Source
Thrown at modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PythonClientCodegen.java:880
CodegenProperty owner = memberNameOwners.putIfAbsent(memberName, property);
if (owner != null
&& !owner.baseName.equals(property.baseName)
&& (explicitPublicName || owner.vendorExtensions.containsKey(
CodegenConstants.X_PY_EXPLICIT_PUBLIC_NAME))) {
throw new IllegalArgumentException(String.format(Locale.ROOT,
"properties %s and %s in model %s both use Python member name %s",
owner.baseName, property.baseName, model.name, memberName));
}
}
}
for (CodegenProperty property : generatedProperties) {
if (!property.vendorExtensions.containsKey(
CodegenConstants.X_PY_PUBLIC_NAME_DIFFERS_FROM_STORAGE)) {
continue;
}
CodegenProperty inputOwner = inputNameOwners.get(property.name);
if (inputOwner != null && !inputOwner.baseName.equals(property.baseName)) {
throw new IllegalArgumentException(String.format(Locale.ROOT,
"property %s in model %s uses generated storage name %s, "
+ "which is an input name for property %s",
property.baseName, model.name, property.name, inputOwner.baseName));
}
}
}
private Set<String> generatedModelMembers(CodegenModel model) {
Set<String> members = new HashSet<>(MODEL_PUBLIC_MEMBER_NAMES);
if (compatibleWithPythonLegacy) {
members.addAll(LEGACY_MODEL_METADATA_MEMBER_NAMES);
}
members.addAll(PYDANTIC_PRIVATE_MEMBER_NAMES);
for (CodegenModel ancestor = model; ancestor != null; ancestor = ancestor.parentModel) {
if (ancestor.isAdditionalPropertiesTrue) {
members.add("additional_properties");
}
addMangledMember(members, ancestor.classname, "__properties");View on GitHub (pinned to fcec517be3)
Solutions
- Adjust the mapping so no hidden storage name equals another property's wire name or public alias
- Rename the affected property in the spec to break the crossing
- Review the whole model's mapping at once instead of per-property edits; crossings only appear when names cross between two properties
Example fix
# before: properties 'id' and 'user_id' in one model, mapping rotates them openapi-generator-cli generate -i api.yaml -g python --name-mapping user_id=id,id=user_id # after: map to a fresh name that is nobody else's input name openapi-generator-cli generate -i api.yaml -g python --name-mapping user_id=userIdAttr
Defensive patterns
Strategy: validation
Validate before calling
# Ensure no hidden storage name is another property's input name (Python):
input_names = {base for base, public in model_props} | {public for base, public in model_props if public}
for base, storage in mapped_storage_names: # (wire name, storage name after mapping)
assert storage not in input_names, f'storage name {storage} is an input name for another property' Try / catch
try {
new DefaultGenerator().opts(input).generate();
} catch (IllegalArgumentException e) {
// message: 'property X in model M uses generated storage name S, which is an input name for property Y'
// break the crossing: change the mapping so S belongs to only one property
} Prevention
- Never rotate or swap names between two properties with mappings
- When a mapping renames a property, target a fresh name nobody else claims as wire or public input
- Review whole-model mappings rather than per-property patches
When it happens
Trigger: Model with properties 'a' and 'b'; -g python --name-mapping b=a makes b's public name 'a', so b's storage name 'a' (or a sanitized variant) becomes an input name owned by property 'a' - a crossing assignment.
Common situations: Swapping or rotating names between two sibling properties with mappings; legacy specs where a stored field name coincides with another property's wire alias after remapping.
Related errors
- property %s in model %s uses generated Python member name %s
- properties %s and %s in model %s both accept input name %s
- properties %s and %s in model %s both use Python member name
- property %s in model %s cannot use %s as its public Python n
- property %s in model %s has invalid generated Python field n
AI-assisted analysis of OpenAPITools/openapi-generator@fcec517be3 (2026-08-22).
Data as JSON: /api/errors/de89fd32cd60306a.
Report an issue: GitHub.