NuGet
NuGet Symbols and Symbol Packages, Explained
What’s more frustrating than your application crashing? Staring for hours at a useless stack trace with no clue what went wrong. Unlike other package types, NuGet packages are precompiled binaries, making traditional debugging techniques pretty ineffective. Instead, you’re just left guessing, since without Symbols, stepping-through your code isn’t an option.
You’ve probably heard of Symbols (.pdb), Symbol packages (.snupkg), and Source Servers, tools used to fill in that missing info. By using the exact debug Symbols and matching source code, Visual Studio and other debuggers let you step-through your code line-by-line, letting you find where exactly the error occurred—super useful for figuring out the cause of a broken app. But… You’re likely still wondering how it all actually works.
In this article, we’ll break down how NuGet Symbols and Symbol packages work, demystify the tech behind Symbol and Source Serving, and walk through the modern tools—like Source Link and .snupkg files that make debugging NuGet packages easier than ever.
Symbols vs. Symbol Packages
You’ve probably noticed .pdb files hanging out in your bin directory after building your project, alongside your .dll or .exe files. These .pdb files are “Symbol files”—essentially a map linking compiled assemblies (your .dlls and .exes) the original source code (.cs files) that built them.

Visual Studio uses these .pdb files to let you step-through your code line-by-line while you’re debugging on your machine.
Even when you’re not actually debugging, .pdb files give detailed info in stack traces if your app crashes. It’s why you’ll sometimes see the full file path to the original code file—even when your app crashes on a totally different computer.
What are NuGet Symbol packages?
A Symbol package is basically just a NuGet package that contains Symbols (.pdb files) instead of libraries (.dll files) and some different metadata. Oh, and they use a different file extension too: .snupkg instead of the regular .nupkg.

The nuget.exe or dotnet CLI creates a Symbol package at the same time as a normal NuGet package when you specify the SymbolPackageFormat argument, For example:
nuget pack MyPackage.csproj -Symbols -SymbolPackageFormat snupkg
dotnet pack MyPackage.csproj -p:IncludeSymbols=true -p:SymbolPackageFormat=snupkg
Once you run one of these commands, you’d end up with MyPackage.nupkg and MyPackage.snupkg in your working directory: one would have the .dll files, and the other .pdb files.
The regular .nupkg package gets pushed to a NuGet feed (public or private), and the symbols .snupkg package gets pushed to a Symbol Server.

Legacy Symbol Format & Packages
Believe it or not, NuGet Symbol and Source serving was way more complicated only a few years back. If you ever stumble across some of these older packages or formats, don’t worry—here’s the quick rundown so you’re not caught off guard.
Legacy Symbol Packages (.symbols.nupkg)
These days, we mostly use .snupkg files for Symbol packages, but back in the day, legacy packages used a .symbols.nupkg extension. Along with .pdb files, those older packages often included the source code and sometimes even compiled .dll files bundled together.
Microsoft PDB (Legacy Symbol Files)
There’s actually two types of .pdb files out there: Microsoft PDB (sometimes called Windows PDB) and Portable PDB. They might look the same from the file name, but under the hood, they’re totally different.
👴 Microsoft PDBs have existed since the early ’90s and are still used for native Windows driver binaries and .NET Framework assemblies. But they only work on Windows and weren’t built for cross-platform debugging.
👶 Portable PDBs, on the other hand, are a modern rework by the .NET team—cross-platform and designed specifically for .NET libraries.
If you’re building C++ libraries or anything native for Windows, you’ll still be sticking with Microsoft PDBs. But for most.NET devs working with NuGet today, Portable PDBs are what you’ll see.
Try debugging with Symbols
Crashes in your app are frustrating enough —but when the issue is inside a NuGet package, and you don’t have Symbols or Source Files? Good luck. It’s like debugging blindfolded.
If you’ve ever struggled to debug a NuGet package, Symbols and Symbol package are absolutely worth exploring. There are other workarounds—like “munging”—but with ProGet’s built-in symbol support, using Symbols is by far the cleaner and more reliable option.
This article had a lot of quickfire info, and I recommend saving this page to come back to! For even more on using NuGet packages, check out our eBook, “NuGet at Scale”. It covers everything we just discussed, plus it has valuable tips on private package management, version numbers, and more! Get your free copy now!