[protobuf] Message was missing required fields

5,389 views
Skip to first unread message

SyRenity

unread,
Apr 16, 2010, 2:05:57 PM4/16/10
to Protocol Buffers
Hi.

I'm getting occasionally the following error below in my Java app:

com.google.protobuf.InvalidProtocolBufferException: Message was
missing required fields. (Lite runtime could not determine which
fields were missing).
at
com.google.protobuf.UninitializedMessageException.asInvalidProtocolBufferException(UninitializedMessageException.java:
81)
at classes.cameraInfoProto$camera
$Builder.buildParsed(cameraInfoProto.java:242)
at classes.cameraInfoProto$camera$Builder.access
$11(cameraInfoProto.java:238)
at classes.cameraInfoProto
$camera.parseFrom(cameraInfoProto.java:133)
at app.jSockets.FetcherSockets
$ResponseThread.readMessage(FetcherSockets.java:386)
at app.jSockets.FetcherSockets
$ResponseThread.run(FetcherSockets.java:268)


I double-checked my code, but I have only a single required field, and
I'm always filling it up in the C++ app.

Any idea how to diagnose it?

Thanks.

--
You received this message because you are subscribed to the Google Groups "Protocol Buffers" group.
To post to this group, send email to prot...@googlegroups.com.
To unsubscribe from this group, send email to protobuf+u...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/protobuf?hl=en.

Henner Zeller

unread,
Apr 16, 2010, 2:11:19 PM4/16/10
to SyRenity, Protocol Buffers
On Fri, Apr 16, 2010 at 11:05, SyRenity <stas....@gmail.com> wrote:
> Hi.
>
> I'm getting occasionally the following error below in my Java app:
>
> com.google.protobuf.InvalidProtocolBufferException: Message was
> missing required fields.  (Lite runtime could not determine which
> fields were missing).
>        at
> com.google.protobuf.UninitializedMessageException.asInvalidProtocolBufferException(UninitializedMessageException.java:
> 81)
>        at classes.cameraInfoProto$camera
> $Builder.buildParsed(cameraInfoProto.java:242)
>        at classes.cameraInfoProto$camera$Builder.access
> $11(cameraInfoProto.java:238)
>        at classes.cameraInfoProto
> $camera.parseFrom(cameraInfoProto.java:133)
>        at app.jSockets.FetcherSockets
> $ResponseThread.readMessage(FetcherSockets.java:386)
>        at app.jSockets.FetcherSockets
> $ResponseThread.run(FetcherSockets.java:268)
>
>
> I double-checked my code, but I have only a single required field, and
> I'm always filling it up in the C++ app.

Just a wild guess: is it an enumeration field that you extended
recently ? If you set the new value in the C++ app, but the Java code
is still compiled with the old version that does not know about that
enumeration value, that non-matching enum field is stashed away in an
'unknown field' instead of ending up in the enum which the application
might not be able to handle - thus the required field is not set.
Could it be this ?

-h

Kenton Varda

unread,
Apr 19, 2010, 1:51:14 PM4/19/10
to SyRenity, Protocol Buffers
If Henner's answer didn't help, you'll need to provide a small, self-contained example which reproduces the problem.

Patrick Linehan

unread,
Mar 10, 2015, 9:09:30 PM3/10/15
to prot...@googlegroups.com, stas....@gmail.com
Nearly 5 years later, I found myself having the same problem.  Perfectly-valid serialized protobufs generated in C++ for message types with no required fields suddenly started throwing "InvalidProtocolBufferException: Message was missing required fields." exceptions in Java.

The problem is, as far as I can tell, a bug in the Dalvik JIT.  I've never seen in in ARM devices, but have seen it in x86 on Android 4.4.4.  Disabling the JIT (setting "android:vmSafeMode" to true in the AndroidManifest.xml) resolves the problem.

It all comes down to a sign extension bug in the following code:

 private byte memoizedIsInitialized = -1;
    public final boolean isInitialized() {
      byte isInitialized = memoizedIsInitialized;
      if (isInitialized != -1) return isInitialized == 1;

      memoizedIsInitialized = 1;
      return true;
    }
The value of isInitialized will be implicitly converted to an int (for comparison to -1 and 1) and, in certain cases, won't be sign extended, giving a value of 255.  This in turn causes the function to return false.  This bug appears to be completely random, and doesn't require racing threads.  I don't know if this bug is during the initial store of the field or in the subsequent load, exactly.

A simple workaround is to modify the compiler output to make both memoizedIsInitialized and isInitalized into ints. This avoids any need for casting or sign extension.

Stephen Tu

unread,
Mar 11, 2015, 2:33:58 AM3/11/15
to Patrick Linehan, prot...@googlegroups.com, stas....@gmail.com
On Tue, Mar 10, 2015 at 5:09 PM, Patrick Linehan <plin...@gmail.com> wrote:
A simple workaround is to modify the compiler output to make both memoizedIsInitialized and isInitalized into ints. This avoids any need for casting or sign extension.

Wait what? If this is really the problem, why not make these two variables booleans, for what they really are? 

Patrick Linehan

unread,
Mar 11, 2015, 12:57:02 PM3/11/15
to prot...@googlegroups.com, plin...@gmail.com, stas....@gmail.com, tu.st...@gmail.com
Sorry, I spoke imprecisely.  I did not actually modify the compiler, I just run the resultant code through sed to make some fixups.

In the case where you _do_ have required fields, however, there is additional code in this function which sometimes sets the field to zero, so such a simple sed solution wouldn't work if you used a boolean.

My intention was not (and is not) to be prescriptive about the solution.  I was just hoping to help any poor souls who encountered the same issue.

Neil Young

unread,
Oct 3, 2016, 2:00:58 PM10/3/16
to Protocol Buffers, stas....@gmail.com, plin...@gmail.com
@Patrick: Wow, what a great, great find. Congratulations.

Out of the sudden my very old project came up with the same exception, without any small changed in the code made by me. But as usual Android Studio has changed nearly every day: Updates, deprecations, changes everywhere.

I tried to come down to the reason, but the problem did not appear while I was debugging. This was the first hint which points to the JIT.

The android:vmSafeMode didn't help BTW, seems it has now a different meaning


android:vmSafeMode
Indicates whether the app would like the virtual machine (VM) to operate in safe mode. The default value is "false".

This attribute was added in API level 8 where a value of "true" disabled the Dalvik just-in-time (JIT) compiler.

This attribute was adapted in API level 22 where a value of "true" disabled the ART ahead-of-time (AOT) compiler.


However, your second workaround is OK

Neil Young

unread,
Oct 3, 2016, 2:01:28 PM10/3/16
to Protocol Buffers, stas....@gmail.com, plin...@gmail.com
I filed a bug report https://github.com/google/protobuf/issues/2217.

And it happens on ARM as well. Nexus 6P, Android 7

Regards

Bastien Mayard

unread,
Oct 18, 2016, 2:07:10 PM10/18/16
to Protocol Buffers, stas....@gmail.com, plin...@gmail.com
I reproduced the issue on my Nexus 6P/Android N.

It seems to be linked to InstantRun. When I disable it, code works fine. 

Feng Xiao

unread,
Oct 18, 2016, 2:08:36 PM10/18/16
to Bastien Mayard, Protocol Buffers, stas....@gmail.com, plin...@gmail.com
On Mon, Oct 17, 2016 at 8:17 AM, Bastien Mayard <may...@gmail.com> wrote:
I reproduced the issue on my Nexus 6P/Android N.

It seems to be linked to InstantRun. When I disable it, code works fine. 
Can you add this info to the issue tracker: https://github.com/google/protobuf/issues/2217 ?
 

--
You received this message because you are subscribed to the Google Groups "Protocol Buffers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to protobuf+unsubscribe@googlegroups.com.

To post to this group, send email to prot...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages