44

One of the attractive features of protocol buffers is that it allows you extend the message definitions without breaking code that uses the older definition. In the case of an enum according to the documentation:

a field with an enum type can only have one of a specified set of constants as its value (if you try to provide a different value, the parser will treat it like an unknown field)

therefore if you extend the enum and use the new value then a field with that type in old code will be undefined or have its default value, if there is one.

What is a good strategy to deal with this, knowing that in future the enum may have additional values added?

One way that comes to mind is to define an "undefined" member of the enum and make that the default, then old code will know it has been sent something that it can't interpret. Is that sensible, are there better ways to deal with this situation?

3
  • A further solution is to never add values to an existing enum, but instead add a new one. Commented May 3, 2012 at 20:44
  • 3
    From the code I've been staring at today (Java), it's not clear that a default value helps. The enum field already has a default value (the first value of the enum), but that value is assigned and unset. Thus, the isInitialized() fails, because the scan of the required fields sees that the hasField boolean is false. Enum, required, extendable - pick any two? Commented Aug 17, 2012 at 19:55
  • @VoiceOfUnreason: Correct: if you make the enum required, unexpected values will be seen as incompatible. Having a default only helps if it's optional. Commented Jun 19, 2013 at 6:27

2 Answers 2

34

Yes, the best approach is to make the first value in the enum something like UNKNOWN = 0. Then old programs reading a protobuf with an enum value they don't recognize will see it as UNKNOWN and hopefully they can handle that reasonably, eg by skipping that element.

If you want to do this you'll also want to make the enum be optional not required.

required, generally, means "I'd rather the program just abort than handle something it doesn't understand."

Note that it must be the first value declared in the proto source - just being the zero value doesn't make it the default.

Sign up to request clarification or add additional context in comments.

2 Comments

I tested with Protocol Buffer Version 3 and if a client tries to unmarshal an enum that has a new value (not yet present in the client proto), it doesn't map to the first value (UNKNOWN=0 in the example), it simply throws an exception. This behaviour caused me to use String instead of enum, because it would create a coupling between the client and server.
@Toyo Can you provide a sample code where you see this behaviour?
7

At least in the java implementation of proto3, it creates a default value. The value will start with "UNKNOWN_ENUM_VALUE_"

Code references:

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.