{"record":{"id":"b369af47f294584f","repo":"OpenAPITools/openapi-generator","slug":"property-s-in-model-s-has-invalid-generated-pyth","errorCode":null,"errorMessage":"property %s in model %s has invalid generated Python field name %s","messagePattern":"property (.+?) in model (.+?) has invalid generated Python field name (.+?)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PythonClientCodegen.java","lineNumber":845,"sourceCode":"                throw new IllegalArgumentException(String.format(Locale.ROOT,\n                        \"property %s in model %s uses generated Python member name %s\",\n                        property.baseName, model.name, generatedMemberName));\n            }\n            if (explicitPublicName\n                    && (!publicName.matches(\"[A-Za-z_][A-Za-z0-9_]*\")\n                    || PYTHON_KEYWORDS.contains(publicName)\n                    || publicName.startsWith(\"__\"))) {\n                throw new IllegalArgumentException(String.format(Locale.ROOT,\n                        \"property %s in model %s cannot use %s as its public Python name\",\n                        property.baseName, model.name, publicName));\n            }\n            if (explicitPublicName\n                    && (!property.name.matches(\"[A-Za-z][A-Za-z0-9_]*\")\n                    || PYTHON_KEYWORDS.contains(property.name)\n                    || MODEL_FIELD_NAME_COLLISIONS.contains(property.name)\n                    || MODEL_CLASS_BODY_NAMES.contains(property.name)\n                    || PYDANTIC_PRIVATE_MEMBER_NAMES.contains(property.name))) {\n                throw new IllegalArgumentException(String.format(Locale.ROOT,\n                        \"property %s in model %s has invalid generated Python field name %s\",\n                        property.baseName, model.name, property.name));\n            }\n\n            for (String inputName : List.of(property.baseName, publicName)) {\n                CodegenProperty owner = inputNameOwners.putIfAbsent(inputName, 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 accept input name %s\",\n                            owner.baseName, property.baseName, model.name, inputName));\n                }\n            }\n            for (String memberName : List.of(property.name, publicName)) {\n                CodegenProperty owner = memberNameOwners.putIfAbsent(memberName, property);\n                if (owner != null","sourceCodeStart":827,"sourceCodeEnd":863,"githubUrl":"https://github.com/OpenAPITools/openapi-generator/blob/fcec517be3cf5b7964296bcba25fbc97541484e7/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PythonClientCodegen.java#L827-L863","documentation":"Separately from the public name, the python generator validates the generated storage/field name (the attribute name on the pydantic model) whenever an explicit public name is in play. The storage name must match [A-Za-z][A-Za-z0-9_]* (must start with a letter), not be a Python keyword, and not be one of the model field name collisions, model class body names, or pydantic private member names the generator reserves.","triggerScenarios":"-g python --name-mapping foo=_bar (mapped storage name starts with underscore, failing the stricter [A-Za-z]... regex), or a mapping that makes the storage name one of the reserved class-body/pydantic names such as schema, model_fields, or fields.","commonSituations":"Using an underscore-prefixed mapping target to 'hide' a field; mapping onto pydantic internals like model_dump or schema; migrating mappings between generator versions as the reserved-name lists grew.","solutions":["Change the mapping target so the storage name starts with a letter and is not a keyword or reserved model/pydantic name","Rename the source property in the spec so its sanitized storage name is clean","Check the reserved lists in PythonClientCodegen (MODEL_FIELD_NAME_COLLISIONS, MODEL_CLASS_BODY_NAMES, PYDANTIC_PRIVATE_MEMBER_NAMES) and avoid those exact names"],"exampleFix":"# before\nopenapi-generator-cli generate -i api.yaml -g python --name-mapping payload=_internal,model_fields=mf\n# after\nopenapi-generator-cli generate -i api.yaml -g python --name-mapping payload=internal,model_info=mf","handlingStrategy":"validation","validationCode":"# Validate a mapping-derived storage name (Python):\nimport keyword\nSTORAGE_RE = re.compile(r'^[A-Za-z][A-Za-z0-9_]*$')  # note: must start with a letter\nRESERVED = {'schema', 'fields', 'model_fields', 'model_dump', 'model_computed_fields'}  # extend from PythonClientCodegen\ndef valid_storage(name: str) -> bool:\n    return bool(STORAGE_RE.match(name)) and not keyword.iskeyword(name) and name not in RESERVED\n\nassert all(valid_storage(t) for t in mapping_targets)","typeGuard":null,"tryCatchPattern":"try {\n    new DefaultGenerator().opts(input).generate();\n} catch (IllegalArgumentException e) {\n    // message: 'property X in model Y has invalid generated Python field name Z'\n    // pick a storage name starting with a letter, not a keyword, not a pydantic/model reserved name\n}","preventionTips":["Do not use underscore-prefixed mapping targets; storage names must start with a letter","Treat pydantic v2 internals (model_*) as off-limits for storage names","Re-run the mapping lint whenever you upgrade the generator, since reserved-name lists grow"],"tags":["python","codegen","naming","identifier","pydantic","openapi-generator"],"backgroundTag":"invalid-identifier-name","analyzedSha":"fcec517be3cf5b7964296bcba25fbc97541484e7","analyzedAt":"2026-08-22T11:13:11.613Z","schemaVersion":2},"datasetVersion":"2026-08-22T14:17:55.899Z"}