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

  1. Adjust the mapping so no hidden storage name equals another property's wire name or public alias
  2. Rename the affected property in the spec to break the crossing
  3. 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

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


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