Posted On: 2021-04-26
While working on my project, I recently encountered a warning in Unity that I'd never seen before:
Unity is only able to load mdb or portable-pdb symbols. [Filename] is using a legacy pdb format.Faced with a message I didn't understand, I did what any developer would do: I searched for it. Unfortunately, what I found was a lot of confusion and, frankly, some pretty bad advice. It was only by searching for the individual pieces that I was able to discern what was going on. Fortunately, it turns out that the message is actually quite clear if you understand the underlying concepts. Thus, I am writing this blog post to help the next person who searches for the message directly.
In short, this warning means Unity can't load debug symbols for the specified file. This won't stop your project from building, but debugging may be more difficult, as important information (ie. line numbers in errors) may be missing or incorrect. You can fix the issue by either converting the pdb file into the format used by Mono (MDB) or by configuring the offending project to generate the (new) Portable PDB format instead of the old one.
A PDB (aka. Program Database) is a file that describes the debugging information for a corresponding binary (either a .dll or .exe file). It is, among other things, a reference for how the compiled code (which is trimmed down and optimized) relates back to its original source code. Without a PDB (or something equivalent), it would be impossible to tell which instruction corresponds to which line in the source code (in most programs this isn't a one-to-one relationship.)
PDBs predate C#, and were originally designed for programs that compiled into native instructions for Windows (C/C++). When Microsoft first made C#, however, they decided to extend PDBs to fit their needs, rather than create something new. This also had the effect of locking in the debug files so they only worked in Windows - which wasn't really an issue at the time, as Microsoft's implementation was already Windows-only.
When Mono was developed as a cross-platform .NET alternative (based on the C# and CLI design specifications), they found that PDBs were not a suitable solution for storing debug information. The PDB spec is complex, proprietary, and sparsely documented, so the Mono developers were forced to create an alternative (MDB) in order to compile and debug across their various supported platforms. As Unity is cross-platform and built on top of Mono, it was designed to use MDB files as well**.
By the time Microsoft created its own cross-platform implementation of C# and the CLI (.NET Standard), they'd decided it was time to move away from the old PDB format, and instead create a new (confusingly-named) "Portable PDB" format. This new format was written from the ground up, and designed to be simpler, open-source, and clearly documented. In time, Mono was updated to be able to read Portable PDBs, and the newest versions of Unity can do so as well.
So far as I can tell, Unity has never supported debugging with the legacy PDB files, but, until recently, there was no explicit message making it clear that was the case. Instead, Unity would act as though it only had the DLL - executing fine but occasionally causing developer confusion as debugging information was incorrect or incomplete. Importantly, this didn't affect projects complied within Unity - instead, these issues generally only happened to developers who were using code compiled separately: either third party libraries or their own libraries compiled using Microsoft's compiler (instead of Mono).
Interestingly, Unity itself didn't address this issue (the lack of a warning) directly - instead, it is the Visual Studio IDE integration that's providing this new warning*. This approach does make a bit of sense: if you're using the Visual Studio IDE, it is likely you've compiled other projects using that same IDE - and therefore PDBs could very well be first-party libraries (as it was in my case.) Unfortunately, that's not always true - as is evidenced by the IDE integration code explicitly skipping over PDBs from other Unity packages**.
There are two main ways to go about fixing the issue: either generate Portable PDBs, or convert the legacy PDBs into MDBs. For this post, I'll assume that you want to do the former - there are plenty of other resources online documenting the latter approach*. Generating Portable PDBs is quite simple: you merely need to change the "Debugging Information" property of your project. To do so (using Visual Studio), open up your project's build settings (right-click the project -> Properties -> Build tab). Set the Configuration dropdown to the desired value** and open the "Advanced" settings. This will give access to the "Debugging Information" section, allowing you to change it to "Portable". That's it - the next build will output Portable PDBs rather than the proprietary PDB format.
Unfortunately, if you are seeing this warning for a third-party library, you may not be able to fix it. Converting the PDB to MDB might be possible, but if the third-party library is coming from a package source (such as Open UPM), you won't be able to change the package contents. In that case, your best bet is to reach out to the third party (ie. by reporting an issue). Alternately, you could just ignore the warning altogether (as long as you aren't debugging the third-party code, it shouldn't affect you.)
A simple way to avoid this issue is to target a cross-platform framework (such as .NET Standard) in the first place. Generally this is easiest to do when first setting up the project, but with a bit of work it's also possible to migrate an existing project*. Doing so also has the advantage of avoiding accidentally including Windows-only dependencies in the project (such as WinForms). The workflow for doing this during a project's initial setup is very simple (just pick a .NET Standard template from the new project wizard). Unfortunately, this approach won't work for every project, as .NET Standard provides only a subset of the APIs that are present in .NET Framework.
As you can see, legacy PDB warnings are not a big deal: they don't cause significant issues, and in many cases can be fixed by changing a single build setting. Although the warnings only appear to those who use Visual Studio with Unity, anyone who uses .NET Framework libraries can benefit from making that change. I hope this post has helped you to understand the warning - both how to fix it and the underlying reason why it exists.