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

  1. Give every --name-mapping entry a distinct target that matches no other property's generated name in the same model
  2. Deduplicate the spec: keep one canonical casing per concept (prefer snake_case) so sanitized member names cannot clash
  3. 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

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


AI-assisted analysis of OpenAPITools/openapi-generator@fcec517be3 (2026-08-22). Data as JSON: /api/errors/afceba92e1ad222e. Report an issue: GitHub.