YAML — язык конфигурации современной инфраструктуры: он исполняет ваши GitHub Actions, манифесты Kubernetes, стеки Docker Compose и CI/CD-конвейеры. Он также один из самых подверженных ошибкам форматов при ручном написании, поскольку один неправильно выровненный пробел, невидимая табуляция или неэкранированное двоеточие приводят либо к жёсткому сбою парсинга, либо к молча неверному документу. Это руководство охватывает каждую категорию ошибок YAML, как читать сообщения парсеров и самый быстрый способ обнаружить и исправить каждую из них.
Почему ошибки YAML трудно отлаживать
YAML выводит свою структуру целиком из пробельных символов. Здесь нет скобок, фигурных скобок, явных разделителей блоков — только уровни отступов и двоеточия. Это делает YAML на удивление читаемым, когда он корректен, и на удивление раздражающим, когда нет: тот же символ, что упорядочивает ваши данные, может молча их разрушить, если сместиться на одну колонку.
Парсер сообщает, где сдался, а не где вы допустили ошибку
Ключевая сложность сообщений об ошибках YAML в том, что парсеры сообщают строку, на которой перестали интерпретировать документ, — а не строку, где была допущена исходная ошибка. Отсутствующее двоеточие в строке 15 может не проявиться как ошибка до строки 22, когда следующий ключ придёт в неожиданном контексте. Это значит, что почти всегда нужно смотреть на несколько строк выше указанной ошибки, чтобы найти настоящую причину.
- Ошибки отступов каскадируются — неверно отбитый родительский блок заставляет каждый дочерний ключ сообщать об ошибке
- Табуляции выглядят как пробелы, но вызывают сбой парсинга в любом парсере, соответствующем спецификации
- Дублирующиеся ключи молча проходят базовые синтаксические проверки — одно значение перезаписывается без всякого предупреждения
- Неэкранированные спецсимволы вроде :, #, * и & неожиданно меняют смысл документа
- Якоря и алиасы молча дают сбой, если алиас ссылается на несуществующий якорь в том же файле
Note
Версия YAML имеет значение
Большинство современных инструментов ориентируются на YAML 1.2, который ужесточил несколько правил парсинга, разрешённых в YAML 1.1. Например, YAML 1.1 трактовал yes, no, on и off как булевы значения; YAML 1.2 — нет. Если ваша конфигурация использует эти голые строки, а валидатор сообщает о неожиданном приведении типов, причина — расхождение версий YAML. Всегда проверяйте, какую версию спецификации реализует ваш парсер времени выполнения.
Самые частые синтаксические ошибки YAML
Ошибки YAML укладываются в небольшое число повторяющихся категорий. Распознавание категории по сообщению об ошибке — или по внешнему виду файла — сокращает время диагностики с минут до секунд.
Ошибки отступов
YAML требует единообразных отступов. Спецификация не предписывает конкретное число пробелов, но каждый уровень должен быть отб́ит глубже родителя на одну и ту же величину внутри этого блока. Смешивание отступов в два и четыре пробела в одном файле или отступ элемента последовательности на один пробел меньше соседнего даст ошибку «неожиданный отступ» или «не удалось найти ожидаемый элемент блока». Самая безопасная практика — два пробела на уровень по всему файлу.
Табуляции вместо пробелов
Спецификация YAML явно запрещает табуляции как отступы. Большинство парсеров выдают ошибку «найден символ, который не может начать ни один токен» или «табуляция в начале строки», столкнувшись с ней. Проблема невидима в большинстве редакторов, пока вы не включите опцию «показывать пробелы» или «отображать пробелы». Настройте редактор всегда превращать табуляции в пробелы для файлов .yaml и .yml, чтобы полностью исключить эту категорию.
Warning
Неэкранированные строки со спецсимволами
YAML резервирует несколько символов для структурных целей: двоеточие, решётку, звёздочку, амперсанд, восклицательный знак, вертикальную черту, знак «больше», квадратные и фигурные скобки. Когда любой из этих символов появляется в неэкранированном строковом значении, парсер может принять его за синтаксический токен. Самое частое проявление — значение URL вроде https://example.com:8080, вызывающее ошибку «mapping values are not allowed here», потому что :8080 парсится как новый ключ маппинга. Экранируйте (берите в кавычки) любое строковое значение, содержащее эти символы.
| Тип ошибки | Типичное сообщение парсера | Корневая причина | Исправление |
|---|---|---|---|
| Отступы | "could not find expected :" | Блок отбит на неверном уровне | Выровнять по родителю + 2 пробела |
| Табуляция | "character that cannot start token" | Табуляция вместо пробела | Заменить все табуляции пробелами |
| Неэкранированное двоеточие | "mapping values not allowed here" | Двоеточие в голом строковом значении | Взять значение в кавычки |
| Дублирующийся ключ | Тихо или зависит от реализации | Один и тот же ключ дважды в блоке | Удалить или переименовать дубликат |
| Неопределённый алиас | "found undefined alias" | * ссылается на необъявленный & якорь | Объявить якорь до алиаса |
| Многострочный скаляр | Парсер останавливается посреди блока | Неверный индикатор блочного скаляра | Использовать | для literal, > для folded |
| Булево приведение | Неверный тип во время выполнения | yes/no/on/off в режиме YAML 1.1 | Взять строку в кавычки: "yes" |
Как читать сообщения об ошибках YAML
Сообщения об ошибках YAML печально известны своей лаконичностью. Умение расшифровать два-три фрагмента информации, которые они действительно дают, экономит значительное время отладки. Каждое сообщение парсера содержит ссылку на строку и колонку, описание того, что ожидалось, а иногда и описание того, что было найдено вместо этого.
Ошибка в строке 30, колонка 1, обычно означает, что проблема началась в строке 20. Читайте вверх.
Три части сообщения об ошибке парсера
- Строка и колонка: указывает, где парсинг провалился, а не обязательно где ошибка — смотрите на 5–10 строк выше
- Ожидаемый токен: что искал парсер — «ожидалось значение маппинга» значит, что он ждал двоеточие после ключа
- Найденный токен: что парсер встретил на самом деле — «найден элемент блочной последовательности» значит, что наткнулся на элемент списка -, где ожидал ключ
Расшифровка типичных паттернов сообщений
"could not find expected ':'" значит, что парсер прочитал ключ маппинга, но достиг конца строки или токена, не являющегося двоеточием, прежде чем нашёл разделитель. Ключ может содержать зарезервированный символ, который преждевременно оборвал токен ключа, или двоеточие случайно опустили. "mapping values are not allowed here" значит, что : появился в контексте, где парсер не находился в блоке маппинга — обычно из-за неэкранированного URL или строки версии. "found duplicate key" выдают строгие парсеры (yaml.v3 в Go, ruamel.yaml), когда одно и то же имя ключа встречается в блоке более одного раза — изменение конфигурации, при котором старый ключ не удалили.
Tip
Как обнаружить и исправить ошибки YAML пошагово
Самый быстрый путь от сломанного YAML-файла к рабочему — структурированный процесс с учётом категорий, а не построчное разглядывание. Эти пять шагов покрывают все типовые сценарии.
Сначала провалидируйте исходный документ
Откройте Валидатор YAML и вставьте весь документ. Если валидатор сообщает об ошибках, запишите номера строк и категории сообщений до внесения изменений. Исправление по одной ошибке с повторной валидацией после каждого исправления предотвращает случайное внесение новых проблем при исправлении исходных.
Исправьте ошибки отступов и табуляций
Включите отображение пробельных символов в редакторе (VS Code: View → Render Whitespace → All). Замените каждую табуляцию двумя пробелами. Убедитесь, что каждый дочерний блок отбит ровно на два пробела глубже родителя. Элементы последовательности (-) считаются уровнем отступа: содержимое после - должно быть на той же строке или с отступом в два пробела на следующей. Повторно провалидируйте после этого шага, прежде чем продолжать.
Возьмите в кавычки строки со спецсимволами
Просмотрите каждое неэкранированное строковое значение, содержащее двоеточия, решётки, звёздочки, амперсанды, восклицательные знаки или вертикальные черты. Заключите их в двойные кавычки. Особое внимание уделите URL, строкам версий вроде v2.0:latest и значениям, начинающимся с фигурной или квадратной скобки (они будут распарсены как flow-коллекции, а не строки). После экранирования повторно провалидируйте, чтобы подтвердить, что ошибки маппинга устранены.
Проверьте дублирующиеся ключи
Запустите Детектор дублирующихся ключей YAML на том же документе. Дублирующиеся ключи проходят базовую синтаксическую валидацию, но молча перезаписывают значения во время выполнения — большинство CI/CD-инструментов и Kubernetes применяют последнее встреченное значение, тогда как другие применяют первое. Любое из этих поведений опасно. Удалите или переименуйте все дубликаты, которые найдёт детектор.
Провалидируйте якоря и алиасы, если используете
Если ваш YAML использует & якоря и * алиасы — обычные для файлов values Helm, плейбуков Ansible и сложных конфигов Docker Compose — запустите Валидатор якорей и алиасов YAML. Он проверяет, что каждый алиас ссылается на объявленный якорь, что нет циклических merge-ключей и что имена якорей следуют единым конвенциям.
Валидатор YAML
Вставьте любой YAML-документ и получите мгновенный отчёт об ошибках синтаксиса и структуры с номерами строк и колонок — работает полностью в вашем браузере, ничего не загружается.
Ошибки YAML по типам файлов
Разные типы YAML-файлов притягивают разные паттерны ошибок. Зная, какие ошибки чаще всего встречаются в каждом типе файлов, вы проверяете сначала нужное, вместо того чтобы сканировать весь документ.
Workflows GitHub Actions
Workflows GitHub Actions падают на этапе парсинга до исполнения любого job, поэтому ошибки YAML — первое, что нужно исправить. Самая частая ошибка — on:, трактуемый как булево значение (true), потому что on — булево значение YAML 1.1; возьмите его в кавычки как "on" или используйте полное имя триггера. Блоки run: шагов с многострочными shell-скриптами, использующими неверный индикатор блочного скаляра (folded > вместо literal |), тоже вызывают тихие ошибки, где переводы строк сжимаются. Используйте | для многострочных shell-скриптов. Валидатор workflow GitHub Actions проверяет и синтаксис YAML, и структурные правила workflow за один проход.
Манифесты Kubernetes
Ошибки YAML в Kubernetes обычно связаны с глубоко вложенными ошибками отступов — блок containers, отбитый под spec на четыре пробела, когда окружающие блоки используют два, или блок resources.limits, помещённый на неверный уровень вложенности. API-сервер Kubernetes сообщает о них как об ошибках валидации полей, а не как об ошибках синтаксиса YAML, потому что kubectl apply сначала успешно парсит YAML, а затем валидирует схему объекта. Используйте Валидатор Kubernetes, чтобы поймать проблемы и YAML, и уровня схемы до применения. Подсветка diff для JSON/YAML-конфигов полезна для сравнения манифестов между окружениями.
Файлы Docker Compose
Ошибки docker-compose.yml в Docker Compose чаще всего — это ошибки отступов в определениях сервисов, неэкранированные маппинги портов вроде 3000:3000 (двоеточия вызывают ошибку парсера, если не взять их в кавычки или не записать как элемент последовательности) и значения переменных окружения, содержащие знаки равенства или решётки без кавычек. Всегда берите в кавычки значения переменных окружения. Валидатор Docker Compose проверяет и структуру YAML, и специфичную для Compose схему.
Файлы values.yaml Helm
Файлы values.yaml Helm часто используют якоря YAML для DRY-конфигурации — а связанные с якорями ошибки часты после реструктуризации. Валидатор values Helm проверяет специфичный для Helm синтаксис, а Инструмент diff дрейфа YAML для values Helm помогает сравнивать значения между релизами и ловить дрейф, внесённый недавней правкой.
Плейбуки Ansible
Плейбуки Ansible сочетают стандартный YAML с шаблонными выражениями Jinja2, использующими двойные фигурные скобки вокруг имён переменных. Двойные фигурные скобки — не синтаксис YAML, но они встречаются внутри строковых значений YAML. Если выражение Jinja является всем значением ключа без кавычек, YAML-парсер Ansible трактует открывающую фигурную скобку как начало flow-маппинга. Всегда берите в кавычки любое значение YAML, начинающееся с двойных фигурных скобок. Валидатор Ansible обрабатывает и слой YAML, и слой Jinja2 при валидации плейбуков.
Продвинутые категории ошибок YAML
Помимо базового синтаксиса, у нескольких возможностей YAML есть собственные категории ошибок, требующие специфических подходов к диагностике. Они менее распространены, но без правильных инструментов их обычно труднее диагностировать.
Дублирующиеся ключи — тихая потеря данных
Дублирующиеся ключи — самая опасная категория ошибок YAML, потому что в большинстве парсеров они не вызывают сбоя парсинга. Когда вы рефакторите конфиг и добавляете новое значение ключа, не удалив старое, оба ключа сосуществуют в исходном тексте. В зависимости от парсера побеждает первое или последнее значение — PyYAML и js-yaml молча используют последнее вхождение, тогда как yaml.v3 в Go сообщает об ошибке. В результате получается конфиг, который при чтении выглядит корректным, но ведёт себя во время выполнения не так, как вы ожидаете.
Warning
Ошибки якорей и алиасов
Якоря YAML (&name) позволяют определить значение один раз и ссылаться на него в других местах через алиас (*name). Ошибки возникают, когда алиас ссылается на якорь, объявленный позже в файле (прямые ссылки в YAML не допускаются), когда два якоря имеют одно имя (второй молча перезаписывает первый) или когда merge-ключ (<<: *alias) используется на узле, не являющемся маппингом. Эти ошибки невидимы для базовых валидаторов — их поймает лишь валидатор, который специально отслеживает объявления якорей и ссылки алиасов.
Расхождения подстановки переменных окружения
Docker Compose, GitHub Actions и Ansible поддерживают подстановку переменных окружения внутри значений YAML. Когда переменная окружения не задана на момент парсинга, подстановка либо проваливается, либо использует пустую строку, либо откатывается к значению по умолчанию — в зависимости от использованного синтаксиса. YAML-документ, корректно валидируемый в CI, может упасть в продакшене, потому что отсутствует требуемая переменная окружения. Инструмент предпросмотра подстановки env в YAML позволяет предпросмотреть развёрнутый YAML-документ с конкретным набором значений переменных перед деплоем.
- $VAR без значения по умолчанию: тихо даёт сбой, если VAR не задана — подставляет пустую строку
- Синтаксис ${VAR:-default}: откатывается к "default", если VAR не задана — тестируйте оба пути
- Синтаксис ${VAR:?error message}: выбрасывает явную ошибку, если VAR не задана — предпочтительно для обязательных переменных
- Неэкранированные подстановки, начинающиеся с фигурной скобки: парсер трактует подстановки переменных как flow-маппинги — всегда берите в кавычки
Как предотвратить ошибки YAML в долгосрочной перспективе
Исправлять отдельные ошибки YAML быстро, когда известна категория. Чтобы они не доходили до продакшена, нужен небольшой набор устойчивых привычек и автоматических проверок.
Настройка редактора
Настройте редактор использовать отступы в два пробела для YAML-файлов, вставлять пробелы вместо табуляций и включить отображение пробелов. В VS Code установите расширение YAML от Red Hat — оно даёт проверку синтаксиса в реальном времени, валидацию схемы (для Kubernetes, GitHub Actions и других форматов с опубликованными JSON-схемами) и автодополнение. Добавьте файл .editorconfig в проект, чтобы принудительно применять эти настройки для каждого члена команды независимо от локальной конфигурации его редактора.
- Настройки .editorconfig для YAML: indent_style = space, indent_size = 2, trim_trailing_whitespace = true
- VS Code: установите расширение YAML (Red Hat) — оно валидирует схему и синтаксис в реальном времени
- IDE JetBrains: включите поддержку YAML и установите уровень инспекции Warning для структурных ошибок
- Vim/Neovim: используйте yaml-language-server через nvim-lspconfig для встроенной диагностики
- Prettier: единообразно форматирует YAML — предотвращает дрейф пробелов и отступов между членами команды
Автоматическая валидация в CI/CD
Добавьте шаг линтинга YAML в CI-конвейер, выполняющийся на каждом pull request, затрагивающем любой файл .yaml или .yml. yamllint — стандартный CLI-инструмент: он проверяет синтаксис, ищет дублирующиеся ключи, соблюдает лимиты длины строк и ловит проблемы приведения truthy-строк. Настройте его через файл .yamllint.yaml в корне проекта и добавьте как pre-commit-хук или шаг CI перед любыми job деплоя.
Tip
Дисциплина ревью кода
Диффы YAML в ревью кода обманчиво легко одобрять, не замечая ошибок. Отступы в два против четырёх пробелов выглядят как предпочтение форматирования, но меняют структуру документа. Ключ, перемещённый на другой уровень отступа, меняет свой родительский блок. Используйте Подсветку diff для JSON/YAML-конфигов, чтобы ревьюить изменения YAML семантически — она показывает, какие ключи добавлены, удалены или изменены по значению, а не построчным диффом, делая структурные изменения сразу видимыми.
Подсветка diff для JSON/YAML-конфигов
Сравнивайте два YAML-конфига на уровне путей ключей, чтобы ловить структурные изменения, перемещённые ключи и обновления значений — лучше сырых построчных диффов для ревью инфраструктуры.
Key takeaways
- Отступы и табуляции вызывают большинство ошибок YAML — настройте редактор использовать пробелы и показывать пробельные символы.
- Ошибки парсеров YAML указывают, где парсинг провалился, а не где была допущена ошибка — всегда смотрите на 5–10 строк выше указанной строки.
- Дублирующиеся ключи — самая опасная категория ошибок: они успешно парсятся, но молча перезаписывают значения во время выполнения.
- Неэкранированные строки с двоеточиями, решётками, звёздочками или фигурными скобками трактуются как структурные токены YAML — всегда берите их в кавычки.
- Используйте Валидатор YAML для синтаксических ошибок, Детектор дублирующихся ключей YAML для тихих перезаписей и Валидатор якорей и алиасов YAML для проблем с якорями.
- Добавьте yamllint в CI-конвейер и .editorconfig в проект, чтобы ошибки YAML не доходили до ревью кода.
- Валидаторы, специфичные для типов файлов (Kubernetes, Docker Compose, GitHub Actions, Ansible), ловят ошибки схемы, которые одна лишь валидация синтаксиса YAML не найдёт.