Compiler Error Messages

I’ve spent a fair amount of time lately tweaking the C# compiler’s error messages.  At some point I begin to wonder, how clearly do we have to spell things out for end users?  There are at least 2 dozen different error messages that could be summarized with just “not an l-value”.  Now granted, there is an extreme.  Some compilers and tools do little more than tell you an error happened, and sometimes where it happened.  I believe an error message should indicate what is wrong, and if possible how to fix it.  So my question for anybody who reads this an actually uses C#, do you feel like the compiler error messages are good or bad?  If you can give me specific examples maybe I can get a few things fixed before we ship 😉


Comments (18)

  1. Clear compiler messages are a godsend! Most developers have no idea what an l-value is, so you should do your best to explain what’s wrong and how to fix it.

    The old Apple/IBM/HP Taligent C++ compiler (later sold to HP) had the best compiler error messages I ever encountered. I especially liked the unknown variable error message, which searched the known variables for a near match. It was something like this:

    Don’t know variable "froo", did you mean "foo"?

    It wasn’t always correct, but it often was.

  2. In this case, it’s better to add than to remove.

    Some of the starting developers where I work, who had experience with VC++ 6 enjoy them a lot.

    Why do you even consider removing this?

  3. Grant,

    Probably the most confusing for new C# developers — whether they have an extensive background in C++ or not — has to do with the famous Unknown type message, (paraphrase) "Have you forgotten an assembly reference or using directive?". C++ developers in particular get stumped ’cause they’re used to having 2 different sets of errors: one group from the preprocessor/compiler, and another group from the linker. And if they’re new to C#, they don’t get it that metadata is resolving both the #include and linker issues.

    Of course, when this error occurs, you’re not gonna know which problem it is: you only know that you can’t resolve the type that they’re referencing. But experience teaching .NET has shown me that more of the time the problem is the lack of an assembly reference. So perhaps a better msg might suggest that they first check their assembly references, and if those are complete, then to try using the fully qualified name or add a using directive?

    If you wanted to get really clever, a way to optionally list all the friendly names of the referenced assemblies and all the using directives that are in scope could be interesting, but it’d have to be optional: once they get comfortable, they’d hate that (I would!).

    Hope this helps.


  4. Ilya Ryzhenkov says:

    The one I’d like to be fixed/added is using debug info of referenced assembly (if any) when showing related point. For example, I have 2 assemblies, one have interface defined and second one uses that interface. If you don’t implement all members of interface, it correctly shows error, but it gives useless reference:

    CorePhone.cs(10,15): error CS0535: ‘Core.Phone’ does not implement interface member ‘Framework.ICoreObject.Modified’

    CorebinDebugFramework.dll: (Related file)

    However, if related position were in same assembly, it gives correct source point.

  5. Ian Ringrose says:

    As a C++ programmer I think the C# compilers error messages are good.

    However people from a VB background think they are not very helpful.

    You should however be able to do a LOT better then a C++ compiler, keeping an ex c++ programmer happy is a VERY low bar!

    I do not mind if you need to “rerun” the compiler when you find an error, so as to get enough information for a useful error message. You only have to be fast in the case were the code has no errors.

    E.g. if I use the wRong case for a method name, you should be able to tell me the name of the method(s) that matches on all but case. If I misspell a method name, you should be able to list “close” method names. Likewise for class names. If the class I use is not find due to a missing #using, you should be able to list all namespaces that constrains a class with that name.

    ringi at bigfoot dot c0m

  6. Mark Blomsma says:


    As the compiler needs to cater to beginning and advanced C# programmers, so does the error message need to have several levels.

    A basic one that will probably have enough information for 90% of the cases, but when you go to the details of the message there is additional info.


  7. Taco in den Bosch says:

    The one error message that comes to mind is CS0104: ambiguous reference. The compiler displays the relevant locations, but it should also display the fully qualified names.

    The Visual Studio task list is even worse: it only displays ‘X’ is an ambiguous reference, without an indication of which types it could refer to.

  8. I see a lot of good suggestions here about what the compiler should spit out. I don’t think that I can add any suggestions as to WHAT to spit out, but I have one on HOW to show it.

    Why not create an XML schema for compiler messages and output XML that conforms to that schema? In it, you could have an error code, an error description (localized or non), a pointer to a link with more information on the error, suggestions, pointers, etc, etc.

    And then this would be great for tools like MSBuild, because we could just process the output very easily (with .NET or any other programming language practically). It definitely beats a custom format and opens up the compiler output for extensibility, IMO.

  9. Keith Hill says:

    Hmmm, I’d just be able if the errors/warnings were listed in order of occurrence in the task list instead of whatever order they are in (alpha?). I’m pretty happy with the quality of the messages even if they are a bit long. I am happy to see that in Whidbey we might get multiline display of error messages cool. And before someone mentions it, I do know how to turn off the auto-display of the task list window after a build with errors. I just find too many other developers tripping up on attacking what they *think* is the first error and wasting time because that error is a side effect of the *real* first error.

  10. Keith Hill says:

    Oops. That should’ve read "I’d just be happy if the errors/warnings …"

  11. Roaan Vos says:

    When using auto generated version numbers (and even when not) and all assiemblies are not in sync, I quite often get something like (dont’ have exact wording now) "Could not copy assembly foo because it conflicts with foo"

    What would be REALLY helpfull is if the compiler told me which assemblies reference the various conflicting assemblies. That way I can easily fix the incorrect assemblies.

  12. James Slaughter says:

    I live in the land of C++ and am well-trained in reading huge error messages, but I spent a few minutes in C# today. An error message that I particularly didn’t like was:

    "Cannot convert null to ‘foo’ because it is a value type"

    The error message seems to have it backwards: the subject of the sentence is null. I’m pretty sure my struct foo is a value type and the error message says that null is, too. So, I can’t convert because their both value types, or what? 🙂

    Obviously, I didn’t sweat over this one, but it looks silly.

  13. Grant says:

    Thanks for the feedback. Just in case you’re still confused by the error message, the "it" is referring to ‘foo’ not to the ‘null’. Hopefully we can get this cleaned up grammatically for the next release.

    The rest of this reply I’m going to put as a separate post.

  14. I am looking for help in understanding error messages I have one that is driving me crazy. "unexpected end of file"

    This was an important file that I used almost everyday and when I call it up all I get is: unexpedted end of file’ Can I get it back? and How.


    Connie, In Memphis, Tennessee

  15. Scott says:


    Unexpected end of file usually indicates a missing closing brace, semicolon, ), etc.

    for example,

    public class xyz


    public void method()




    A closing brace is missing. I close method() but not xyz(), although the indentation makes it look as if xyz is closed.

  16. Scott says:

    The above post may make more sense if the indentation appears correctly, so here is another shot:

    public class xyz


        public void method()




  17. Scott says:

    Oh well. It was worth a shot.