OpenAPITools/openapi-generator · error · IllegalArgumentException
properties %s and %s in model %s both use Python member name
Error message
properties %s and %s in model %s both use Python member name %s
What it means
The python generator also tracks the Python member names (storage name and public name) produced for each property in a model. When explicit public names are in play and two different properties end up using the same member name, generation aborts, because the class body would contain two attributes or aliases with identical names.
Source
Thrown at modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PythonClientCodegen.java:867
for (String inputName : List.of(property.baseName, publicName)) {
CodegenProperty owner = inputNameOwners.putIfAbsent(inputName, 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 accept input name %s",
owner.baseName, property.baseName, model.name, inputName));
}
}
for (String memberName : List.of(property.name, publicName)) {
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));
}
}View on GitHub (pinned to fcec517be3)
Solutions
- Give every --name-mapping entry a distinct target that matches no other property's generated name in the same model
- Deduplicate the spec: keep one canonical casing per concept (prefer snake_case) so sanitized member names cannot clash
- Run generation, read the two property names in the message, and rename one of them in the spec or mapping
Example fix
# before: model has 'user_id' and 'userId'; mapping collapses both openapi-generator-cli generate -i api.yaml -g python --name-mapping user_id=id,userId=id # after: keep one property in the spec, no collapsing mapping openapi-generator-cli generate -i api.yaml -g python --name-mapping user_id=id
Defensive patterns
Strategy: validation
Validate before calling
# Ensure no two properties produce the same Python member name (Python):
def member_names(props):
names = []
for base, public in props:
names.append(sanitize(base)) # generated storage name
if public:
names.append(public) # public member name
return names
seen = set()
for n in member_names(model_props):
assert n not in seen, f'two properties use member name {n}'
seen.add(n) Try / catch
try {
new DefaultGenerator().opts(input).generate();
} catch (IllegalArgumentException e) {
// message: 'properties A and B in model M both use Python member name N'
// make mapping targets unique per model and rerun
} Prevention
- Avoid specs that mix casing variants of the same concept (userId vs user_id) in one model
- Deduplicate mapping targets mechanically (sort + uniq check) before generating
- Apply mappings model-by-model and review the diff of generated models
When it happens
Trigger: -g python --name-mapping a=x,b=x (two wire names mapped to the same member name), or a mapping target that equals another property's generated storage name after sanitization (e.g. wire names 'userName' and 'user_name' in one model with one of them mapped).
Common situations: Specs that mix naming conventions (camelCase and snake_case variants of the same concept, e.g. userId and user_id) combined with --name-mapping; bulk-generated mappings from a spreadsheet that reuse target names.
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
- property %s in model %s uses generated storage name %s, whic
- 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/afceba92e1ad222e.
Report an issue: GitHub.