OpenAPITools/openapi-generator · error · ProtoBufIndexComputationException

Generated field number is in reserved range (19000, 19999).

Error message

Generated field number is in reserved range (19000, 19999).

What it means

The protobuf-schema generator does not let you write field numbers in the .proto output; it derives them deterministically from each property name via Math.abs(name.hashCode() % 536870911). Protocol Buffers reserves field numbers 19000-19999 for the protobuf implementation itself, so when a computed hash lands in that window the generator aborts with ProtoBufIndexComputationException instead of emitting an invalid .proto file that protoc would reject.

Source

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

    @Override
    public String getTypeDeclaration(Schema p) {
        if (ModelUtils.isArraySchema(p)) {
            Schema inner = ModelUtils.getSchemaItems(p);
            return getSchemaType(p) + "[" + getTypeDeclaration(inner) + "]";
        } else if (ModelUtils.isMapSchema(p)) {
            Schema inner = ModelUtils.getAdditionalProperties(p);
            return getSchemaType(p) + "<string, " + getTypeDeclaration(inner) + ">";
        }
        return super.getTypeDeclaration(p);
    }

    private int generateFieldNumberFromString(String name) throws ProtoBufIndexComputationException {
        // Max value from developers.google.com/protocol-buffers/docs/proto3#assigning_field_numbers
        int fieldNumber = Math.abs(name.hashCode() % 536870911);
        if (19000 <= fieldNumber && fieldNumber <= 19999) {
            LOGGER.error("Generated field number is in reserved range (19000, 19999) for %s, %d", name, fieldNumber);
            throw new ProtoBufIndexComputationException("Generated field number is in reserved range (19000, 19999).");
        }
        return fieldNumber;
    }

    /**
     * Extracts enum properties from models and creates separate enum model files.
     * Also adds imports to the parent models for the extracted enums.
     *
     * @param objs the models map containing all models
     * @return the modified models map with extracted enum models added
     */
    private ModelsMap extractEnumsToSeparateFiles(ModelsMap objs) {
        List<Map<String, String>> enumImports = new ArrayList<>();

        Map<String, CodegenModel> extractedEnums = this.extractEnums(objs);
        for (String enumName : extractedEnums.keySet()) {
          // Add an import for this enum to the parent model
          String enumImportPath = toModelImport(toModelName(enumName));

View on GitHub (pinned to fcec517be3)

Solutions

  1. Rename the offending property in the OpenAPI spec (the error log line prints the name and number); any rename changes the hash and moves the number out of 19000-19999
  2. Pre-compute the field number for every property name (abs(javaHash(name) % 536870911)) to find all colliding names before generation, then rename each one
  3. If the wire name must not change, introduce a wrapper/rename at the API layer or maintain the .proto by hand instead of using -g protobuf-schema
  4. Report/upvote the issue on openapi-generator GitHub so explicit field numbers (e.g. via a vendor extension) get supported

Example fix

# before: spec property whose hash lands in 19000-19999
components:
  schemas:
    Pet:
      properties:
        keyCode:   # abs(hashCode % 536870911) in reserved range -> generation fails
          type: string
# after: rename the property (wire name changes, hash moves out of range)
components:
  schemas:
    Pet:
      properties:
        keyCodeValue:
          type: string
Defensive patterns

Strategy: validation

Validate before calling

# Pre-check every property name against the generator's field-number hash (Python):
def java_hash(s: str) -> int:
    h = 0
    for c in s:
        h = (31 * h + ord(c)) & 0xFFFFFFFF
    if h >= 0x80000000:
        h -= 0x100000000
    return h

def reserved(name: str) -> bool:
    return 19000 <= abs(java_hash(name) % 536870911) <= 19999

bad = [p for p in all_property_names(spec) if reserved(p)]
assert not bad, f'rename these properties, they hash into 19000-19999: {bad}'

Try / catch

try {
    new DefaultGenerator().opts(clientOptInput).generate();
} catch (ProtoBufIndexComputationException e) {
    // log the property name from the preceding LOGGER.error line and fail the build fast
    throw new IllegalStateException('protobuf field number reserved-range collision, rename the reported property', e);
}

Prevention

When it happens

Trigger: Running openapi-generator with -g protobuf-schema against a spec that contains a property (or any named field that goes through generateFieldNumberFromString) whose Java String.hashCode mod 536870911 falls in 19000..19999. The failure is deterministic: the same property name always fails, every run.

Common situations: Adding or renaming a property in the OpenAPI spec changes its hash and can suddenly push it into the reserved window (~0.19% chance per field). Teams with large specs hit it eventually; it also appears when migrating an existing spec to the protobuf-schema generator, and the same spec generates fine for other languages because only this generator hashes names into field numbers.

Related errors


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