OpenAPITools/openapi-generator · error · IllegalArgumentException

property in model has invalid generated Python field name

Error message

property %s in model %s has invalid generated Python field name %s

What it means

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.

Solutions

  1. Change the mapping target so the storage name starts with a letter and is not a keyword or reserved model/pydantic name
  2. Rename the source property in the spec so its sanitized storage name is clean
  3. Check the reserved lists in PythonClientCodegen (MODEL_FIELD_NAME_COLLISIONS, MODEL_CLASS_BODY_NAMES, PYDANTIC_PRIVATE_MEMBER_NAMES) and avoid those exact names

Example fix

# before
openapi-generator-cli generate -i api.yaml -g python --name-mapping payload=_internal,model_fields=mf
# after
openapi-generator-cli generate -i api.yaml -g python --name-mapping payload=internal,model_info=mf
Defensive patterns

Strategy: validation

Validate before calling

# Validate a mapping-derived storage name (Python):
import keyword
STORAGE_RE = re.compile(r'^[A-Za-z][A-Za-z0-9_]*$')  # note: must start with a letter
RESERVED = {'schema', 'fields', 'model_fields', 'model_dump', 'model_computed_fields'}  # extend from PythonClientCodegen
def valid_storage(name: str) -> bool:
    return bool(STORAGE_RE.match(name)) and not keyword.iskeyword(name) and name not in RESERVED

assert all(valid_storage(t) for t in mapping_targets)

Try / catch

try {
    new DefaultGenerator().opts(input).generate();
} catch (IllegalArgumentException e) {
    // message: 'property X in model Y has invalid generated Python field name Z'
    // pick a storage name starting with a letter, not a keyword, not a pydantic/model reserved name
}

Prevention

When it happens

Trigger: -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.

Common situations: 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.

Related errors


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

Appendix: source

Thrown at modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PythonClientCodegen.java:845

                throw new IllegalArgumentException(String.format(Locale.ROOT,
                        "property %s in model %s uses generated Python member name %s",
                        property.baseName, model.name, generatedMemberName));
            }
            if (explicitPublicName
                    && (!publicName.matches("[A-Za-z_][A-Za-z0-9_]*")
                    || PYTHON_KEYWORDS.contains(publicName)
                    || publicName.startsWith("__"))) {
                throw new IllegalArgumentException(String.format(Locale.ROOT,
                        "property %s in model %s cannot use %s as its public Python name",
                        property.baseName, model.name, publicName));
            }
            if (explicitPublicName
                    && (!property.name.matches("[A-Za-z][A-Za-z0-9_]*")
                    || PYTHON_KEYWORDS.contains(property.name)
                    || MODEL_FIELD_NAME_COLLISIONS.contains(property.name)
                    || MODEL_CLASS_BODY_NAMES.contains(property.name)
                    || PYDANTIC_PRIVATE_MEMBER_NAMES.contains(property.name))) {
                throw new IllegalArgumentException(String.format(Locale.ROOT,
                        "property %s in model %s has invalid generated Python field name %s",
                        property.baseName, model.name, property.name));
            }

            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

View on GitHub (pinned to fcec517be3)