{"record":{"id":"de89fd32cd60306a","repo":"OpenAPITools/openapi-generator","slug":"property-s-in-model-s-uses-generated-storage-nam","errorCode":null,"errorMessage":"property %s in model %s uses generated storage name %s, which is an input name for property %s","messagePattern":"property (.+?) in model (.+?) uses generated storage name (.+?), which is an input name for property (.+?)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PythonClientCodegen.java","lineNumber":880,"sourceCode":"                CodegenProperty owner = memberNameOwners.putIfAbsent(memberName, property);\n                if (owner != null\n                        && !owner.baseName.equals(property.baseName)\n                        && (explicitPublicName || owner.vendorExtensions.containsKey(\n                                CodegenConstants.X_PY_EXPLICIT_PUBLIC_NAME))) {\n                    throw new IllegalArgumentException(String.format(Locale.ROOT,\n                            \"properties %s and %s in model %s both use Python member name %s\",\n                            owner.baseName, property.baseName, model.name, memberName));\n                }\n            }\n        }\n        for (CodegenProperty property : generatedProperties) {\n            if (!property.vendorExtensions.containsKey(\n                    CodegenConstants.X_PY_PUBLIC_NAME_DIFFERS_FROM_STORAGE)) {\n                continue;\n            }\n            CodegenProperty inputOwner = inputNameOwners.get(property.name);\n            if (inputOwner != null && !inputOwner.baseName.equals(property.baseName)) {\n                throw new IllegalArgumentException(String.format(Locale.ROOT,\n                        \"property %s in model %s uses generated storage name %s, \"\n                                + \"which is an input name for property %s\",\n                        property.baseName, model.name, property.name, inputOwner.baseName));\n            }\n        }\n    }\n\n    private Set<String> generatedModelMembers(CodegenModel model) {\n        Set<String> members = new HashSet<>(MODEL_PUBLIC_MEMBER_NAMES);\n        if (compatibleWithPythonLegacy) {\n            members.addAll(LEGACY_MODEL_METADATA_MEMBER_NAMES);\n        }\n        members.addAll(PYDANTIC_PRIVATE_MEMBER_NAMES);\n        for (CodegenModel ancestor = model; ancestor != null; ancestor = ancestor.parentModel) {\n            if (ancestor.isAdditionalPropertiesTrue) {\n                members.add(\"additional_properties\");\n            }\n            addMangledMember(members, ancestor.classname, \"__properties\");","sourceCodeStart":862,"sourceCodeEnd":898,"githubUrl":"https://github.com/OpenAPITools/openapi-generator/blob/fcec517be3cf5b7964296bcba25fbc97541484e7/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PythonClientCodegen.java#L862-L898","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"# before: properties 'id' and 'user_id' in one model, mapping rotates them\nopenapi-generator-cli generate -i api.yaml -g python --name-mapping user_id=id,id=user_id\n# after: map to a fresh name that is nobody else's input name\nopenapi-generator-cli generate -i api.yaml -g python --name-mapping user_id=userIdAttr","handlingStrategy":"validation","validationCode":"# Ensure no hidden storage name is another property's input name (Python):\ninput_names = {base for base, public in model_props} | {public for base, public in model_props if public}\nfor base, storage in mapped_storage_names:  # (wire name, storage name after mapping)\n    assert storage not in input_names, f'storage name {storage} is an input name for another property'","typeGuard":null,"tryCatchPattern":"try {\n    new DefaultGenerator().opts(input).generate();\n} catch (IllegalArgumentException e) {\n    // message: 'property X in model M uses generated storage name S, which is an input name for property Y'\n    // break the crossing: change the mapping so S belongs to only one property\n}","preventionTips":["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"],"tags":["python","codegen","naming","name-collision","openapi-generator"],"backgroundTag":"property-name-collision","analyzedSha":"fcec517be3cf5b7964296bcba25fbc97541484e7","analyzedAt":"2026-08-22T11:13:11.613Z","schemaVersion":2},"datasetVersion":"2026-08-22T14:17:55.899Z"}