Again, I want to emphasize that any program which expects parse failures to happen during normal operation is probably doing something wrong. Whether or not the parser accepts a message actually tells you very little about the integrity of the message. Remember that the parser is designed to be tolerant of unexpected information in the message, since this is how it provides forward- and backward-compatibility.
For example, take these two messages:
message A {
optional int32 i = 1;
required bool b = 2;
}
enum E { FOO = 1; BAR = 2; }
message B {
optional double d = 1;
repeated E e = 2;
}
What do you think would happen if you had a valid encoded message of type A and you tried to parse it as a B. Guess what? It succeeds. In fact, *any* valid protocol message of *any* type will parse successfully as a B, since B has no required fields.
But what if you parsed a B as an A? A has a required field, and B doesn't even have any fields of that type, so it can't succeed, right? Wrong. Booleans and enums are both encoded as varints in the wire. So if B.e is non-empty, then A will interpret it as a value of A.b, satisfying the required field.
Now, you say that you are doing extra validation afterwards which you are convinced will ensure that a B cannot be mistaken for an A or vice versa. This could work, but I still think it is a hacky approach, and hacky approaches tend to lead to unexpected problems down the road. If at all possible, you should move to using the AorB message I proposed earlier.
All that said, the reason for the error message is simply for debugging help: It identifies exactly which field was missing from the message. Typically the caller doesn't particularly care which field was missing, since it will reject message regardless. However, a developer testing the program would be very interested to know what was missing. We discovered that without this message, it was very hard to debug these kinds of errors. In general, error messages logged by libprotobuf are for such debugging purposes.
If you want to avoid printing this error, what you should really do is use one of the Message::ParsePartial*() methods when parsing. This skips the required fields check, and will never print an error message. You can manually call IsInitialized() on the result to check for required fields yourself -- this also will not log any errors.
Another alternative is to use LogSilencer:
But using ParsePartial will avoid even constructing the error message, which can be expensive.