Plugin Output is Unparsable — Logging in a Protobuf Plugin

Logging to stdout is not possible when using protoc. To avoid that, write to stderr or use a framework that does it for you or logs to a file instead.

David Groemling
Cloud Native Daily
3 min readMay 29, 2023

--

A screenshot of an error-message generated by protoc, indicating unparsable output of a protoc plugin.
Error message in protoc indicating unparseable output.

protoc-gen-*: Plugin output is unparseable: ..., did you ever receive this error-message? Logging is an essential tool for most software developers to understand failures and find bugs. Yet, protoc can make this complicated and the above error-message is often the result. Here’s how you can log anyways. The code is available on GitHub.

What’s the problem?

Protoc uses stdin and stdout to communicate with its plugins. If a logger writes to stdout, protoc tries to parse that output. Since the log-statement is meant to be read by humans, this parsing will fail. Therefore, a protoc plugin cannot use stdout for anything else but communicating code generation results back to protoc.

What can be done?

1. Just print to stderr

A straight-forward solution is to just print to stderr instead of stdout. In the example of python, you can do that, by specifying a file in a print-statement:

print("Generating protobuf...", file=sys.stderr)

If you make that change, protoc will succeed:

Screenshot of a successful code-generation run, with output printed to stderr.
Successful code-generation run, when printing to stderr.

This approach works and may be the simplest one, if you just need things to work quickly. For a more permanent solution, I recommend using a proper logging framework.

2. What’s better? — Use a logging framework

Logging frameworks offer more flexibility like logging to files, different log-levels or printing the file name and line where the log occurs. In fact, the Python logging facility, by default, writes its output to stderr . To use it, first configure the logger. To be on the save side, you can specifically set the stream to stderr. Then log something:

import logging

logger = logging.getLogger(__name__)
logging.basicConfig(
stream=sys.stderr,
level=logging.INFO, format="%(asctime)s - %(name)s - %(levelname)s - %(filename)s:%(lineno)d - %(message)s"
)

if __name__ == "__main__":
logger.info("Generating protobuf...")

...

The result is a working compilation with a good amount of extra helpful information and the flexibility to redirect logs to a file for later analysis.

Screenshot of a successful code-generation run with extra logging output due to the usage of a logging framework.
A working example using the python logging facility

Conclusion

Logging to stdout is not possible when using protoc. To avoid that, write to stderr or use a framework that does it for you or logs to a file instead.

Do you want to know more about writing protoc plugins? Check out my series on that topic.

--

--