Node.js 24.20.0: assert больше не падает на Map с null-ключом. Безопасный runbook для edge case: фиксируем наблюдения, возвращаем baseline и не делаем лишних выводов.
Подтверждённый факт и предел вывода
Официальный changelog Node.js 24.20.0 LTS фиксирует конкретное изменение: исправлен TypeError в assert и util для Map с null-ключами. Проверяемая пользовательская проблема уже: вместо полезного diff assertion сам formatter выбрасывает TypeError на Map с null-ключом. Release note не доказывает массовость, причину любого похожего сбоя или совместимость приложения целиком. До опыта запишите версию бинарника, способ запуска и ожидаемый класс результата. Разделяйте наличие изменения в релизе, воспроизведение на стенде и разрешение на production-миграцию: это три разных утверждения.
Изолированный fixture и baseline
Подготовьте только синтетический стенд: две Map с null-ключом, одинаковой структурой и одним различающимся примитивным значением. Сначала выполните ветку A на текущем разрешённом runtime и сохраните наблюдаемые поля, затем B на Node.js 24.20.0, после чего верните A2. Меняйте один фактор — версию или точную опцию — и ставьте конечный timeout. Не используйте production database, реальные домены, ключи, cookies, токены, пользовательские файлы или полные переменные окружения. Если A и A2 расходятся, стенд загрязнён и причинный вывод откладывается.
Матрица наблюдений без догадок
Для каждого прогона заполните строку: assert method × тип ключа × тип расхождения × класс ошибки × наличие diff. Значения должны быть получены напрямую: код завершения, тип ошибки, счётчик, fingerprint тестового объекта или явный state. Не записывайте «стало лучше» и не делайте вывод из одного общего лога. Повторите B минимум в той же последовательности, но не превращайте повторы в нагрузочный тест. Отдельно отметьте версию Node.js и то, остались ли исходные синтетические данные неизменными после опыта.
Контрольная ветка и дерево решения
Независимый control для этой проверки: такие же Map со строковым ключом и тем же различием. Он нужен, чтобы отделить свойство API от ошибки fixture, платформы или порядка событий. Примените заранее записанное дерево: получен AssertionError с diff — исправление видно; TypeError остался — фиксируем версию; тест проходит — fixture не содержит различия. Не объединяйте отсутствие симптома и исправление: если A не воспроизводится, B ничего не доказывает. Если control даёт тот же неожиданный результат, вернитесь к минимальному примеру и не меняйте рабочую конфигурацию.
Красные флаги и остановка
Стоп-критерий здесь конкретный: не менять библиотеку сравнения во всём проекте по одному edge case до проверки вложенной Map и circular reference. Немедленно остановите прогон также при выходе за временный каталог, неожиданном сетевом соединении, запросе повышенных прав, повреждении fixture, отсутствии timeout или невозможности вернуть A2. Crash, зависание, расхождение повторов и результат, который нельзя отнести к одному классу, — не повод подбирать удобное объяснение. Это основание сохранить минимальный case и отложить rollout.
Минимизированная эскалация
Для поддержки достаточно передать: короткий assert-скрипт, типы ключей, error.name и первые строки diff без рабочих объектов. Добавьте время по Москве, архитектуру, точную версию Node.js, команду только с несекретными флагами, ожидаемый класс и фактический класс результата. Удалите домашние пути, адреса, содержимое базы, реальные hostname, ключи, authorization headers и длинные сырые логи. Такой пакет должен позволять воспроизвести одну границу и выбрать следующий обратимый тест, а не раскрывать рабочую среду.
Протокол проверки №10: assert-map-null-key-diff
Шаг 1 — зафиксируйте ровно эту исходную боль: вместо полезного diff assertion сам formatter выбрасывает TypeError на Map с null-ключом. Шаг 2 — подтвердите только релизную границу «исправлен TypeError в assert и util для Map с null-ключами», не приписывая changelog пользовательскую частоту. Шаг 3 — создайте единицу опыта «две Map с null-ключом, одинаковой структурой и одним различающимся примитивным значением» и дайте ей отдельный временный каталог. Шаг 4 — до изменения заполните поля «assert method × тип ключа × тип расхождения × класс ошибки × наличие diff», чтобы baseline был проверяемым. Шаг 5 — выполните независимый контроль «такие же Map со строковым ключом и тем же различием»; его результат не подменяет основную ветку. Шаг 6 — сравните классы исходов по правилу «получен AssertionError с diff — исправление видно; TypeError остался — фиксируем версию; тест проходит — fixture не содержит различия». Шаг 7 — верните исходное состояние и повторно снимите именно «assert method × тип ключа × тип расхождения × класс ошибки × наличие diff». Шаг 8 — при любом неясном результате примените запрет «не менять библиотеку сравнения во всём проекте по одному edge case до проверки вложенной Map и circular reference». Шаг 9 — сформируйте артефакт только из следующего набора: короткий assert-скрипт, типы ключей, error.name и первые строки diff без рабочих объектов. Шаг 10 — удалите синтетический fixture и убедитесь, что не осталось процесса, listener, test key, временной базы или изменённого trust state. Успех протокола №10 означает лишь воспроизводимость границы «исправлен TypeError в assert и util для Map с null-ключами» на этом стенде. Он не означает, что зависимость приложения совместима, rollout разрешён или наблюдение повторится на другой платформе.
Материал подготовлен редакцией VOne с помощью ИИ по открытым официальным и первичным источникам; факты, даты и ссылки перепроверены. Реальные пользовательские данные не использовались.
Источники и проверка
- Node.js 24.20.0 release notes проверено 2026-08-29
- Node.js pull request #64441 проверено 2026-08-29
Информация актуальна на дату публикации. Правила сервисов, приложений и сетей могут меняться.