apache/flink · error · PbCodegenException

Illegal type for protobuf enum, only char/vachar/int/bigint

Error message

Illegal type for protobuf enum, only char/vachar/int/bigint is supported

What it means

When a proto field is an ENUM, the deserializer only accepts Flink CHAR/VARCHAR (stringified) or TINYINT/SMALLINT/INTEGER/BIGINT (numeric getNumber()). Any other type root for that column (e.g. BOOLEAN, DOUBLE, DECIMAL) throws this PbCodegenException at codegen time. The message text 'vachar' is a known typo for varchar.

Source

Thrown at flink-formats/flink-protobuf/src/main/java/org/apache/flink/formats/protobuf/deserialize/PbCodegenSimpleDeserializer.java:76

                                + " = BinaryStringData.fromString("
                                + pbObjectCode
                                + ".toString())");
                break;
            case ENUM:
                if (logicalType.getTypeRoot() == LogicalTypeRoot.CHAR
                        || logicalType.getTypeRoot() == LogicalTypeRoot.VARCHAR) {
                    appender.appendLine(
                            resultVar
                                    + " = BinaryStringData.fromString("
                                    + pbObjectCode
                                    + ".toString())");
                } else if (logicalType.getTypeRoot() == LogicalTypeRoot.TINYINT
                        || logicalType.getTypeRoot() == LogicalTypeRoot.SMALLINT
                        || logicalType.getTypeRoot() == LogicalTypeRoot.INTEGER
                        || logicalType.getTypeRoot() == LogicalTypeRoot.BIGINT) {
                    appender.appendLine(resultVar + " = " + pbObjectCode + ".getNumber()");
                } else {
                    throw new PbCodegenException(
                            "Illegal type for protobuf enum, only char/vachar/int/bigint is supported");
                }
                break;
            default:
                throw new PbCodegenException(
                        "Unsupported protobuf simple type: " + fd.getJavaType());
        }
        return appender.code();
    }
}

View on GitHub (pinned to 2f3c205e92)

Solutions

  1. Change the offending column to VARCHAR (stores enum name) or INT/BIGINT (stores enum number) so it matches the proto enum field.
  2. If you need DECIMAL, map to a proto int64/int32 field instead of enum in the .proto, or preprocess the value upstream.
  3. Validate schema against the descriptor with PbSchemaValidationUtils.validatePbStruct before job submission.

Example fix

-- before (proto field 'status' is enum)
status DECIMAL(10,0),
-- after
status INT,  -- or VARCHAR
Defensive patterns

Strategy: validation

Validate before calling

FieldDescriptor fd = descriptor.findFieldByName(col);
if (fd != null && fd.getJavaType() == JavaType.ENUM) {
    LogicalTypeRoot r = colType.getTypeRoot();
    boolean ok = r == LogicalTypeRoot.CHAR || r == LogicalTypeRoot.VARCHAR
            || r == LogicalTypeRoot.TINYINT || r == LogicalTypeRoot.SMALLINT
            || r == LogicalTypeRoot.INTEGER || r == LogicalTypeRoot.BIGINT;
    if (!ok) throw new IllegalArgumentException("Enum field " + col + " must be string or integer");
}

Prevention

When it happens

Trigger: DDL maps an enum proto field to a non-string/non-integer column, e.g. status DECIMAL(10,0) while the proto defines status as enum Status.

Common situations: Inferring the table schema from a data lake/AVRO-like source where enums became strings or decimals, then pointing the same schema at a protobuf message class; evolving the proto field from int to enum without updating the DDL.

Related errors


AI-assisted analysis of apache/flink@2f3c205e92 (2026-08-14). Data as JSON: /api/errors/b7aaff2df6454ffe. Report an issue: GitHub.