apache/flink · error · IllegalArgumentException

get %s descriptors error!

Error message

get %s descriptors error!

What it means

PbFormatUtils.getDescriptor loads the protobuf message class via the thread-context classloader and reflectively invokes its static getDescriptor() method. Any failure (ClassNotFoundException, missing method, invocation exception, wrong type) is wrapped in this IllegalArgumentException with the class name. It is a classpath/wiring problem: the configured protobuf.message-class-name cannot be resolved to a Descriptors.Descriptor in the job's classloader.

Source

Thrown at flink-formats/flink-protobuf/src/main/java/org/apache/flink/formats/protobuf/util/PbFormatUtils.java:125

                fileDescriptor.getOptions().hasJavaPackage()
                        ? fileDescriptor.getOptions().getJavaPackage()
                        : fileDescriptor.getPackage();
        if (fileDescriptor.getOptions().getJavaMultipleFiles()) {
            return javaPackageName + ".";
        } else {
            String outerClassName = getOuterClassName(fileDescriptor);
            return javaPackageName + "." + outerClassName + ".";
        }
    }

    public static Descriptors.Descriptor getDescriptor(String className) {
        try {
            Class<?> pbClass =
                    Class.forName(className, true, Thread.currentThread().getContextClassLoader());
            return (Descriptors.Descriptor)
                    pbClass.getMethod(PbConstant.PB_METHOD_GET_DESCRIPTOR).invoke(null);
        } catch (Exception e) {
            throw new IllegalArgumentException(
                    String.format("get %s descriptors error!", className), e);
        }
    }

    public static boolean isRepeatedType(LogicalType type) {
        return type instanceof MapType || type instanceof ArrayType;
    }

    public static boolean isArrayType(LogicalType type) {
        return type instanceof ArrayType;
    }
}

View on GitHub (pinned to 2f3c205e92)

Solutions

  1. Verify the exact FQCN: it must be the generated message class (e.g. com.example.OrderOuterClass$Order) and match 'protobuf.message-class-name'.
  2. Ensure the jar containing the generated classes is shipped with the job (check the fat jar contents) and not masked by lib/ conflicts.
  3. Regenerate proto classes with the same protoc/protobuf-java version Flink uses.
  4. Confirm getDescriptor() exists: javap or a quick reflection test in the job's classloader.

Example fix

-- before
'protobuf.message-class-name'='com.example.Order'
-- after (nested message class)
'protobuf.message-class-name'='com.example.OrderOuterClass$Order'
Defensive patterns

Strategy: validation

Validate before calling

String cn = "com.example.OrderOuterClass$Order";
Class<?> c = Class.forName(cn, true, Thread.currentThread().getContextClassLoader());
if (c.getMethod("getDescriptor").invoke(null) instanceof Descriptors.Descriptor) {
    // safe to use as protobuf.message-class-name
}

Try / catch

try {
    descriptor = PbFormatUtils.getDescriptor(className);
} catch (IllegalArgumentException e) {
    throw new RuntimeException("Proto class not loadable in job classloader: " + className, e);
}

Prevention

When it happens

Trigger: 'protobuf.message-class-name' points to a class not on the job classpath; the class exists but is not a generated protobuf message (no static getDescriptor); shaded/relocated proto classes where reflection cannot find the method; classloader isolation (planner/user classloader) hiding the proto jar.

Common situations: Proto jar not bundled in the Flink job jar; wrong fully-qualified name (old package after regenerating); proto classes compiled with a different protobuf-java version than the runtime; JAR conflicts in lib/.

Related errors


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