Ошибка «metadata file supplied is not valid metadata file» возникает при компиляции проекта в Visual Studio или при сборке через MSBuild, когда компилятор C# обнаруживает, что подключённая DLL-сборка не является корректным файлом метаданных .NET. Компилятор ожидает управляемую сборку с заголовком CLR, а получает либо повреждённый файл, либо неуправляемую библиотеку, либо файл совсем другого формата. Сборка прерывается, и проект не компилируется до устранения причины.
Чаще всего сообщение сопровождается кодом CS0009 и указывает путь к проблемной DLL. Именно этот путь — главная зацепка для диагностики: по нему можно понять, какая ссылка в проекте сломана и почему. Ниже разберём типовые причины и безопасные способы исправления, не требующие переустановки системы или рискованных действий.
Что означает эта ошибка
Каждая управляемая сборка .NET содержит метаданные — служебную информацию о типах, методах и зависимостях, которую компилятор читает при подключении ссылки. Если файл, указанный в ссылках проекта, не содержит корректных метаданных CLR, компилятор выдаёт ошибку и останавливает сборку.
Важно отличать эту ошибку от похожей CS0006 «Metadata file could not be found»: там файл вообще не найден по указанному пути, а здесь файл существует, но его содержимое непригодно. Это принципиально разные ситуации с разными причинами.
- 🔍 CS0009 — файл найден, но не является валидной сборкой .NET;
- 📁 CS0006 — файл не найден по указанному пути;
- ⚙️ CS0246 — тип или пространство имён не найдены (следствие, а не причина).
Основные причины появления ошибки
Причин несколько, и правильная диагностика экономит время. Проверяйте их в порядке от самых частых к редким.
Повреждённая или недокачанная DLL. Если сборка была скопирована вручную, скачана из интернета или извлечена из архива с ошибкой, файл может быть битым. Прерывание копирования, сбой диска или неполная распаковка NuGet-пакета — типичные сценарии.
Ссылка на неуправляемую (native) библиотеку. Обычная Win32-DLL, написанная на C++, не содержит метаданных .NET. Если такую библиотеку добавить в проект через Add Reference, компилятор закономерно выдаст CS0009. Нативные библиотеки подключаются иначе — через DllImport или как файл, копируемый в выходную папку.
Реже встречаются другие варианты: файл нулевого размера после сбоя сборки зависимого проекта, блокировка DLL антивирусом во время компиляции, ссылка на файл, скачанный из интернета и заблокированный Windows, либо конфликт версий .NET Framework и .NET (Core) между проектами решения.
Диагностика: как найти проблемный файл
Откройте текст ошибки в окне Error List или в выводе сборки и найдите полный путь к DLL. Это первое действие — без него все остальные шаги бессмысленны. Далее проверьте сам файл.
Перейдите по пути из ошибки и посмотрите на файл: его размер (нулевой размер — явный признак сбоя), дату изменения и цифровую подпись в свойствах. Если файл скачан из интернета, откройте Свойства → Общие и проверьте, нет ли отметки о блокировке — при её наличии нажмите Разблокировать.
Быстро проверить, является ли файл управляемой сборкой, можно через утилиту ildasm из SDK или через PowerShell:
[Reflection.AssemblyName]::GetAssemblyName("C:\путь\к\файлу.dll")
Если команда возвращает имя и версию сборки — метаданные валидны, и причина в другом. Если выбрасывает исключение BadImageFormatException — файл действительно не является корректной сборкой .NET.
⚠️ Внимание: не подменяйте проблемную DLL файлом с того же именем из непроверенных источников. Сборки с одинаковыми именами могут иметь разные версии и открытые ключи, что приведёт к новым ошибкам уже на этапе запуска приложения.
Пошаговое исправление ошибки
Начните с самых безопасных и обратимых действий — в большинстве подобных ситуаций проблема решается очисткой артефактов сборки.
☑️ Порядок исправления ошибки CS0009
Удалите папки bin и obj во всех проектах решения — там могут остаться повреждённые промежуточные файлы. Затем очистите кэш NuGet:
dotnet nuget locals all --clear
После этого откройте решение, выполните восстановление пакетов (Restore NuGet Packages) и полную пересборку через Build → Rebuild Solution. Если ошибка сохраняется, проверьте порядок сборки проектов: возможно, зависимый проект падает с собственной ошибкой, оставляя после себя битую или пустую DLL, а CS0009 — лишь следствие. Исправьте первую ошибку в списке, а не последнюю.
Если ссылка указывает на нативную библиотеку
Отдельный частый случай — попытка добавить в ссылки проекта обычную C++-библиотеку. Компилятор C# не может прочитать её метаданные, потому что их там нет в принципе.
Решение зависит от задачи. Для вызова функций нативной DLL используйте P/Invoke с атрибутом DllImport, а сам файл добавьте в проект как содержимое с параметром копирования в выходную директорию. Если библиотека — COM-компонент, её нужно зарегистрировать в системе и подключать через COM-вкладку диалога добавления ссылок, чтобы сгенерировалась управляемая обёртка.
Как отличить управляемую сборку от нативной
Управляемая сборка .NET открывается в ildasm или dotPeek и показывает дерево типов. Нативная DLL в этих инструментах не открывается. Также управляемые сборки обычно имеют в свойствах файла описание с упоминанием .NET, а при проверке через Reflection возвращают AssemblyName.
Сравнение типичных причин и решений
| Причина | Признак | Решение |
|---|---|---|
| Повреждённая DLL | Ошибка после копирования или скачивания | Получить файл заново из источника |
| Битый кэш NuGet | Ошибка после обновления пакетов | dotnet nuget locals all --clear |
| Нативная DLL в ссылках | Библиотека написана на C++ | Использовать DllImport вместо Reference |
| Сбой зависимого проекта | Несколько ошибок, CS0009 не первая | Исправить первую ошибку в списке |
| Заблокированный файл | DLL скачана из интернета | Разблокировать в свойствах файла |
⚠️ Внимание: перед удалением папокbinиobjубедитесь, что там нет вручную размещённых файлов, которых нет в системе контроля версий. Стандартно эти папки содержат только генерируемые артефакты, но в старых проектах встречаются исключения.
Профилактика повторного появления
Чтобы ошибка не возвращалась, подключайте сторонние библиотеки через NuGet, а не прямыми ссылками на файлы — менеджер пакетов контролирует целостность и версии. Добавьте папки bin и obj в .gitignore, чтобы битые артефакты не мигрировали между машинами через репозиторий.
При работе в команде согласуйте версии целевой платформы проектов: смешение .NET Framework и современного .NET в одном решении без явной необходимости — частый источник проблем со ссылками. Если сборка настроена в CI, периодическая чистая сборка (clean build) помогает вовремя заметить подобные проблемы.
Частые вопросы
Чем отличается «metadata file could not be found» от «is not valid»?
Первое сообщение означает, что файл по указанному пути отсутствует — обычно из-за несобранного зависимого проекта. Второе — что файл существует, но его содержимое не является корректной сборкой .NET: он повреждён, пуст или нативный.
Поможет ли переустановка Visual Studio?
Практически никогда. Причина почти всегда в файлах проекта, кэше пакетов или конкретной DLL, а не в самой среде разработки. Начинайте с очистки bin/obj и кэша NuGet.
Ошибка появляется только на одном компьютере из команды — что проверить?
Сравните версии установленных SDK и целевых платформ, очистите локальный кэш NuGet на проблемной машине и проверьте, не блокирует ли антивирус файлы в папке проекта во время сборки.
Можно ли подключить нативную C++ DLL как ссылку?
Нет, напрямую нельзя — у неё нет метаданных .NET. Используйте P/Invoke с атрибутом DllImport либо создайте управляемую обёртку на C++/CLI.
Ошибка возникает при сборке через командную строку, но не в Visual Studio — почему?
Вероятно, используются разные версии MSBuild или SDK. Проверьте, какая версия вызывается в консоли (dotnet --info или путь к MSBuild), и сравните с той, что использует среда разработки.