Why am I being told that my message ID is too large?

A customer asked for help with an error message in the message compiler.

Our message file goes like this:

MessageId = 0x10001
SymbolicName = MSG_ERROR
Language = English
Error %1

When we compile it, we get this error:

MC : error : Message Id value (10001) too large

Our understanding is that we defined our message ID as a DWORD (which is an unsigned 32-bit integer), and the value 0x10001 easily fits inside an unsigned 32-bit integer. Is there a command line switch we need to pass to mc.exe? What are we missing?

What they're missing is that message identifiers are limited to the range 0 through 65535.

One place this limitation is visible is in the header file generated by the message compiler:

//  Values are 32 bit values laid out as follows:
//   3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
//   1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
//  +-+-+-+-+-+---------------------+-------------------------------+
//  |S|R|C|N|r|    Facility         |               Code            |
//  +-+-+-+-+-+---------------------+-------------------------------+
//  where
//      S - Severity - indicates success/fail
//          0 - Success
//          1 - Fail (COERROR)
//      R - reserved portion of the facility code, corresponds to NT's
//              second severity bit.
//      C - reserved portion of the facility code, corresponds to NT's
//              C field.
//      N - reserved portion of the facility code. Used to indicate a
//              mapped NT status value.
//      r - reserved portion of the facility code. Reserved for internal
//              use. Used to indicate HRESULT values that are not status
//              values, but are instead message ids for display strings.
//      Facility - is the facility code
//      Code - is the facility's status code

Observe that the Code field is a 16-bit value.

A copy of this header block is also included in the documentation on event identifiers. Though you have to realize that the thing that the message compiler spits out are event identifiers.

The 16-bit limit is also called out in the C# version of the trace logging interface: Event­Attribute.Event­Id says that "This value should be between 0 and 65535."

But again, this requires that you realize that message files are related to event logging.

One thing that may nudge you to that realization is that the documentation for Message Files is in the Event Logging section of MSDN, and it opens with the sentence, "Each event source should register message files that contain..."

But perhaps the smoking gun is that the documentation for the Message File syntax says Any value specified must fit in 16 bits.

Comments (8)
  1. DWalker says:

    How does the programmer know that “Message_ID” gets put into the field named “Code”?

    “the facility’s status code” does not sound like a “Message ID” to me!

    But then again, the customer said “we defined our message ID as a DWORD”. I wonder where they got that guidance…. Yes, the MS documentation here assumes some knowledge. Programming is hard.

    1. Kirby FC says:

      >>”the documentation for the Message File syntax says Any value specified must fit in 16 bits.”

      Actually, the documentation at that link is a bit confusing and possibly misleading. It beings with:

      The type must be large enough to accommodate the entire message code, such as a DWORD.

      Note the usage of “message code” and DWORD. This certainly would lead you to believe that the message code is a 32 bit number. And I can’t find anything on that page that specifically calls out “16 bits”.

  2. Wolf says:

    public int EventId { get; private set; }
    Property Value
    Type: System.Int32
    The event identifier. This value should be between 0 and 65535.

    Why oh why is this property an Int32? Uint16 is a real thing that exists — oh, sure, it’s not CLS-compliant. -sigh- So close…

    1. Ray Koopa says:

      That’s the same thing like with the notification area tooltip popup time, IIRC. .NET uses Int32 wherever possible to get rid of nasty conversions, though it requires you to read the documentation on WinAPI stuffs sometimes ;D

  3. dave says:

    This is all perfectly obvious stuff to a VMS programmer :-)

    1. Malcolm says:

      I was just thinking VMS when I looked at that ;)

      Useless history lesson follows.
      I remember VMS had multiple severity levels for errors, most of which I remember. From lowest to highest, they were …

      S – Status messages. Not even normally seen, but you might see ‘%SYSTEM-S-NORMAL,. normal successful completion’ occasionally
      I – Informational. Such as ‘%SHOW-I-NOSUCHUSER, no user found with name CHEN’ if you did SHOW USER CHEN and CHEN was not logged on.
      W – Warning messages such as ‘%SYSTEM-W-NOSUCHFILE, no such file’
      E – Error messages, such as ‘%RMS-E-DNF, directory not found’
      F – Fatal errors, such as ‘%SYSTEM-F-VIRTMEM, virtual memory exhausted’

      The error message display could also display up to three levels of nested error messages (not as good as a .NET or Java traceback, but still useful to some extent. For instance if you tried to list a nonexistent directory using the DIRECTORY (you could abbreviate it to DIR…) command, you’d get:

      %DIRECT-F-OPENIN, error opening DSK:[DIR]
      -RMS-E-DNF, directory not found
      -SYSTEM-W-NOSUCHFILE, no such file

      In the example of DIRECT-E-OPENIN, DIRECT was the Facility, E was the severity (error) and OPENIN was the identifier. ‘error opening directory DSK:[DIR] was the text. And you could choose what elements you wished to display using the SET MESSAGE facility. You could run SET MESSAGE /NOFACILITY /NOSEVERITY /NOID /TEXT and all you’d get instead was:

      Error opening DSK:[DIR]
      Directory not found
      No such file

      (It automatically capitalised the first letter of the text).

      Some people did that to make VMS more ‘friendly looking’ when something went wrong.
      One subunit of the company I worked for took it even further and disabled all four elements, meaning you got no error messages. Made things hard to debug (but you could always turn them back on again and rerun to find out what was really going wrong).

      I miss VMS sometimes :) I wonder if there are still any VMS jobs to be found in Scotland …

      1. Malcolm says:

        My memory is hazy as to whether not finding a directory was fatal (%DIRECT-F-OPENIN) or an error (%DIRECT-E-OPENIN). Also these were mapped to bit fields in the error code, and in Digital Command Language (the scripting language VMS and other Digital OSes used, although VMS had the greatest amount of features…) the internal variable $SEVERITY (*) told you how severe your error code was.

        I am sure there were other error levels, and it took up two bits of the error code. Sometimes if undefined values were written in there, you’d get a ‘?’ instead of a letter in your error message.

        Status and Informational error messages indicated an error condition which was not really an error, but just a status.
        Warning messages indicated something which could succeed on a retry. For instance ‘%SYSTEM-W-NOSUCHFILE, no such file’ might succeed on a retry if you trapped the error and created the file.
        Error conditions caused execution to stop but could be trapped and corrected.
        Fatal errors meant things were FUBAR (but you could correct and retry if you were lucky ;) )

  4. cheong00 says:

    This post answered the question in MSDN forum long time ago: https://social.msdn.microsoft.com/Forums/en-US/a76f64c3-a3df-4302-820c-1ad28fdf8103/how-do-i-convert-eventlogentryinstanceid-to-the-simple-event-id-i-see-in-event-viewer?forum=csharplanguage

    We just found how to solve it, but unable to get the idea on why it has to be this way.

    Too bad that the question now goes to the archive so I cannot edit to include a link to here.

Comments are closed.

Skip to main content