Frequently Asked Questions

Why do I get an UnmarshalOutOfBoundsException?

Consider the following interface:

// Slice
interface Example
{
    void op(int i , int j);
}; 

When a client invokes operation op, it supplies two integer parameters. The Ice run time marshals the parameters into the request that it sends on the wire. The request is preceded by a protocol header that, among other things, tells the server the total request size (including the 14-byte header). The server uses this information to read the appropriate number of bytes: it first reads the 14-byte header and checks the total request size. For example, that size might be 31 bytes. The server then reads the remainder of the request, namely, 31−14=17 bytes and places these 17 bytes into a buffer for subsequent unmarshaling. The buffer keeps track of how many bytes of the payload are available for reading and prevents attempts to read more data than was actually contained in the request.

The 17-byte payload of the request contains 8 bytes for the two integer parameters. (The remainder of the payload contains other details about the request, such as the object identity and request ID, among other things.) Once the server has identified the correct target operation, it dispatches the incoming request to the Slice-generated skeleton, which contains the code to unmarshal the two integer parameters. The skeleton retrieves 8 bytes from the unmarshaling buffer and converts them back into integers, and then passes these two integers to the implementation of operation op.

If the unmarshaling code in the skeleton tries to retrieve more data from the buffer than is actually available, the buffer raises an UnmarshalOutOfBoundsException. In plain language, the exception means “I expected a certain amount of data for the parameters of an invocation, but there wasn’t as much data available as there should be.” (Similar arguments apply when a client unmarshals the results of an invocation. In that case, the code goes through much the same actions, except that the unmarshaling is done by a proxy instead of a skeleton, and the data is contained in a reply instead of a request.)

So, how can this exception happen? Unless you are using the dynamic invocation or dispatch interfaces, the cause of this exception is invariably a mismatch in the Slice definitions that are used by client and server. For example, suppose that, originally, the preceding interface looked as follows:

// Slice
interface Example
{
    void op(int i); // Earlier version
}; 

During development, you decided to add the second parameter, to turn the interface into the two-integer version we saw earlier. Suppose you faithfully updated the server with the new version of the interface but, for some reason, you forgot to update the client. When you run client and server, the client runs with the old interface, but the server runs with the new interface. Of course, this means that the client will send only a single integer when it invokes op, but the server expects to receive two integers. This results in an UnmarshalOutOfBoundsException on the server side. (If we reverse the situation, such that the client expects two out-parameters, but the server sends only one, you would see the same exception on the client side instead.)

So, in short, UnmarshalOutOfBoundsException is invariably caused by mis-matched Slice definitions, unless you are using the dynamic invocation or dispatch interfaces (in which case your code contains the mismatch).

Note that you can easily catch Slice mismatches at run time by adding the --checksum option when you compile your Slice definitions. This option creates a dictionary in the generated code that contains a checksum for each Slice type. You can add an operation to the server that returns the dictionary to the client and verif y in the client that the checksums for corresponding Slice types are the same; if they differ, you have mismatched Slice definitions. (Please see the Ice Manual for more details on Slice checksums.)

Copyright © 2008 ZeroC, Inc.