OpenAPITools/openapi-generator · error · IllegalArgumentException

property %s in model %s cannot use %s as its public Python n

Error message

property %s in model %s cannot use %s as its public Python name

What it means

The python generator validates any explicitly mapped public name (--name-mapping) against Python identifier rules: it must match [A-Za-z_][A-Za-z0-9_]*, must not be a Python keyword, and must not start with '__' (dunder names are reserved for the generated class machinery). Violations throw this IllegalArgumentException during model post-processing.

Source

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

                    || legacyMetadataCollision
                    || nameMappingGeneratedMembers.contains(publicName));
            boolean storageNameCollision = generatedMembers.contains(property.name)
                    && (explicitPublicName
                    || legacyMetadataCollision
                    || nameMappingGeneratedMembers.contains(property.name));
            if (publicNameCollision || storageNameCollision) {
                String generatedMemberName = publicNameCollision
                        ? publicName
                        : property.name;
                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)

View on GitHub (pinned to fcec517be3)

Solutions

  1. Choose a target name that starts with a letter or single underscore, contains only [A-Za-z0-9_], and is not a Python keyword
  2. Remove the leading '__' (e.g. use _private or private_)
  3. Rename the property in the spec instead of mapping it to an invalid identifier

Example fix

# before
openapi-generator-cli generate -i api.yaml -g python --name-mapping order_id=1st_order,class_type=class
# after
openapi-generator-cli generate -i api.yaml -g python --name-mapping order_id=first_order,class_type=clazz
Defensive patterns

Strategy: validation

Validate before calling

# Validate a mapping target as a Python public identifier (Python):
import keyword
PUBLIC_RE = re.compile(r'^[A-Za-z_][A-Za-z0-9_]*$')
def valid_public(name: str) -> bool:
    return bool(PUBLIC_RE.match(name)) and not keyword.iskeyword(name) and not name.startswith('__')

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

Try / catch

try {
    new DefaultGenerator().opts(input).generate();
} catch (IllegalArgumentException e) {
    // message: 'property X in model Y cannot use Z as its public Python name'
    // change the --name-mapping target to a valid identifier and rerun
}

Prevention

When it happens

Trigger: -g python --name-mapping foo=1st_choice (starts with digit), foo=__private (dunder prefix), foo=class / foo=return (keyword), foo=two words (space) or foo=empty-string.

Common situations: Mapping wire names to human-friendly labels that contain spaces, hyphens, or leading digits; teams converting camelCase APIs to Python style and picking names like 'from' or 'type' without realizing they are keywords.

Related errors


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