0

I seem to be getting an unexplained System.InvalidOperationException stating that a "Nullable object must have a value" at the point when I'm checking the value of the object for null. Unfortunately I'm only receiving this randomly every 1 out of 1,000,000 messages and cant seem to replicate in my local environment with a simulator, which is why I've turned to you guys for help.

I have a foreach loop processing an array of objects:

ReceivedMessage[] messages = pushFeed.ReceivedMessages.GetOustandingMessages();

foreach (var m in messages)
{
    if (m != null) // only here as a sanity check to ensure m was not somehow null
    {
        if(pushFeed.Feed.ForwardReceivedMessage(m))
            logger.Info("Successfully posted to server");
        else
            logger.Warn("Failed to post to server");
    }
}

Inside ForwardReceivedMessage I'm then checking if the Source object within the message object is null and thats where I seem to be getting the InvalidOperationException.

public bool ForwardReceivedMessage(ReceivedMessage message)
{
    CommToken token;

    if (message.Source == null) // This is the line where the exception is being thrown...?
    {
        logger.Warn("Failed to forward feed with null Source...");

        return false;
    }

    // Do other things...
    return true;
}

The ReceivedMessage object is simply:

public class ReceivedMessage
{
    public long MessageId;
    public MessageBase Payload;
    public IAsset Source;
}

And the Source object is just an interface with the following:

public interface IAsset
{
    int ClientId { get; }

    ushort CommId { get; }

    int DeviceId { get; }

    short DeviceMode { get; set; }

    DateTime? LastReportTime { get; }

    string Name { get; }

    bool? Panic { get; }

    int? PassthroughDeviceId { get; set; }

    DeliveryMethod PrimaryMTDeliveryMethod { get; }

    DeliveryMethod? SecondaryMTDeliveryMethod { get; }

    // ... etc, etc
}

As far as I can see, the only issue can be with the Source object, and simply calling message.Source to check if it is null seems to be what is throwing the InvalidOperationException.

I'm thinking it may have something to do with Source being declared as the interface IAsset as opposed to the object, however even if Source were never assigned I believe I would be able to check that is has a value in an if statement?

Im hoping someone here can explain how/why this would happen, and also provide a solution to how I can check if Source has value or not.

Edit: The full exception printout which I'm getting is:

System.InvalidOperationException: Nullable object must have a value.
   at System.ThrowHelper.ThrowInvalidOperationException(ExceptionResource resource)
   at CompanyName.Division.MessageHandler.Platform.PlatformHandler.ForwardReceivedMessage(ReceivedMessage message) in c:\Git\message-handler\MessageHandler\PlatformFeeds\CompanyName.Division.MessageHandler.Platform\PlatformHandler.cs:line 37
   at CompanyName.Division.MessageHandler.Core.FeedManager.<SendCallback>d__11.MoveNext() in c:\Git\message-handler\MessageHandler\CompanyName.Division.MessageHandler.Core\FeedManager.cs:line 160
K.Pallo
  • 53
  • 7
  • 5
    Please provide a full stack trace to your error. – Sefe Jul 16 '18 at 11:35
  • https://stackoverflow.com/questions/1896185/nullable-object-must-have-a-value – Dmitry Bychenko Jul 16 '18 at 11:35
  • Please put a breakpoint on the `if (message.Source == null)` line. When the breakpoint is hit, please use the `Immediate Window` to check the values of each of these. Please let us know the values. If any of them throw an exception please continue to get the values of the others. a) `message` b) `message.GetType()` c) `message.Source` d) `message.Source.GetType()` – mjwills Jul 16 '18 at 11:56
  • Unfortunately I'm unable to replicate the issue on my local machine so breakpointing on that line as @mjwills suggested isn't of much help. – K.Pallo Jul 16 '18 at 12:36
  • I have added the full exception printout as @Sefe requested – K.Pallo Jul 16 '18 at 12:36
  • @K.Pallo In that case, consider adding logging (of those values I mention, plus the exception `StackTrace` if it occurs) on the production machine - so that when it occurs you have some extra data on hand. – mjwills Jul 16 '18 at 12:37
  • @mjwills thanks for the input - will try and dump the full message in the catch block and see if that provides some further information – K.Pallo Jul 16 '18 at 12:43
  • 1
    It is *not* a NullReferenceException. There is a `Nullable` hidden somewhere that we can't see. Maybe your source code is outdated, a not unlikely c:\Git problem. – Hans Passant Jul 16 '18 at 15:51
  • @Hans Passant I do have nullable variables/objects within the `IAsset` interface which I've updated the post to reflect - but regardless of whether there is nullable variables in the object or not - why would `message.Source == null` throw an InvalidOperationException? – K.Pallo Jul 16 '18 at 18:51
  • 1
    There is no evidence at all that IAsset is involved, it bombs inside PlatformHandler.ForwardReceivedMessage(). Interface method calls never get inlined. You therefore have a hard fact, you know that you are not looking at the correct source code. Get another fact by using a decompiler to look at the assembly, the Debug > Windows > Modules window shows its location. – Hans Passant Jul 16 '18 at 18:53
  • @HansPassant Maybe I'm missing something but in the logged exception I can see `at ...PlatformHandler.cs:line 37` which is `if (message.Source == null)`. While trying to debug this I've added different validations before calling `message.Source` and tried removing the if statement entirely - but the trace always pointed the exception to the first instance of `message.Source` in this case `if (message.Source == null)`. I also compile the solution directly on the server using the MSBuild command so I'm almost certain the if statement is whats causing the exception. Any thoughts? – K.Pallo Jul 16 '18 at 19:11
  • As long as you can't find the `Nullable` then, no, we have no hope of finding it for you. Why you need to rely on the exception trace instead of the debugger is not obvious and a major smell. Just don't ignore my decompiler recommendation, you don't even know yet that it is loading the correct DLL. – Hans Passant Jul 16 '18 at 19:17

0 Answers0