apache/seatunnel · error · SeaTunnelProtobufFormatException

DESCRIPTOR_CONVERT_FAILED

DESCRIPTOR_CONVERT_FAILED

Error message

Protoc compile error, exit code: %s

What it means

Thrown by CompileDescriptor.compileProtoToDescriptor when invoking the external 'protoc' binary to compile a .proto file into a descriptor set and protoc exits with a non-zero status. The exit code is included in the message. This happens lazily when the target descriptor path is needed.

Solutions

  1. Run the same protoc command manually on the node to see protoc's real stderr (only the exit code is logged here)
  2. Install/upgrade protoc and ensure it is on PATH or configure the protoc executable path
  3. Fix proto syntax errors and add missing imports with --proto_path/-I entries covering all imported files
  4. Verify the proto file's parent directory is the correct proto_path root for its import statements

Example fix

// before (shell diagnosis)
protoc --proto_path=/tmp/protos --descriptor_set_out=/tmp/out.desc /tmp/protos/user.proto
// e.g. "user.proto:4:1: File 'google/protobuf/timestamp.proto' was not found"

// after
protoc -I/usr/include -I/tmp/protos --proto_path=/tmp/protos --descriptor_set_out=/tmp/out.desc /tmp/protos/user.proto
Defensive patterns

Strategy: validation

Validate before calling

protoc --proto_path=<dir> --descriptor_set_out=/tmp/test.desc <file>.proto && echo OK || echo "protoc failed: $?"

Type guard

boolean protocAvailable() throws IOException, InterruptedException {
    Process p = new ProcessBuilder("protoc", "--version").start();
    return p.waitFor() == 0;
}

Try / catch

try {
    Path desc = compileDescriptor.targetDescPath(protoDir, protoFile);
} catch (SeaTunnelProtobufFormatException e) {
    log.error("protoc failed (exit code in message). Run protoc manually for stderr.", e);
    throw e;
}

Prevention

When it happens

Trigger: Calling targetDescPath/compileProtoToDescriptor where the generated protoc command ('protoc --proto_path=... --descriptor_set_out=... file.proto') returns non-zero — protoc missing/unexecutable, .proto syntax errors, unresolved imports, or a wrong proto_path.

Common situations: protoc not installed or wrong version on the node; .proto references imports (e.g. google/protobuf/*.proto) not on the include path; proto_path pointing at the wrong parent directory; syntax errors after editing the proto.

Related errors


AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10). Data as JSON: /api/errors/083ae8db6edb145b. Report an issue: GitHub.

Appendix: source

Thrown at seatunnel-formats/seatunnel-format-protobuf/src/main/java/org/apache/seatunnel/format/protobuf/CompileDescriptor.java:87

        FileUtils.writeStringToFile(protoFile.getPath(), protoContent);
        return protoFile;
    }

    private static String compileProtoToDescriptor(File tmpDir, File protoFile)
            throws IOException, InterruptedException {
        String targetDesc = tmpDir + "/.desc";
        new File(targetDesc).deleteOnExit();

        int exitCode =
                Protoc.runProtoc(
                        new String[] {
                            "--proto_path=" + protoFile.getParent(),
                            "--descriptor_set_out=" + targetDesc,
                            protoFile.getPath()
                        });

        if (exitCode != 0) {
            throw new SeaTunnelProtobufFormatException(
                    ProtobufFormatErrorCode.DESCRIPTOR_CONVERT_FAILED,
                    "Protoc compile error, exit code: " + exitCode);
        }
        return targetDesc;
    }

    private static Descriptors.FileDescriptor[] buildFileDescriptors(
            DescriptorProtos.FileDescriptorSet descriptorSet)
            throws Descriptors.DescriptorValidationException {
        List<DescriptorProtos.FileDescriptorProto> fileDescriptors = descriptorSet.getFileList();
        Descriptors.FileDescriptor[] descriptorsArray =
                new Descriptors.FileDescriptor[fileDescriptors.size()];
        for (int i = 0; i < fileDescriptors.size(); i++) {
            descriptorsArray[i] =
                    Descriptors.FileDescriptor.buildFrom(
                            fileDescriptors.get(i), new Descriptors.FileDescriptor[] {});
        }
        return descriptorsArray;

View on GitHub (pinned to cf67b549a7)