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.

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.

Appendix: 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)