# Діагностика (довідник DIAG_*)

Кожен код DIAG_*, який видає AfterPack, що його спричинило, як це виправити, і коди виходу, які повертає збірка.

Source: https://www.afterpack.dev/uk/docs/diagnostics

AfterPack ніколи не випускає слабший захист, ніж ви запитали. Коли щось не вдається розв'язати автоматично, збірка зупиняється з іменованим кодом `DIAG_*` і конкретним способом виправлення.

## Рівні серйозності

Кожна діагностика, яку видає AfterPack, має рівно один із трьох рівнів серйозності. Рівня `Warning` немає.

| Рівень | Значення | Що відбувається |
|---|---|---|
| **Info** | Очікувана поведінка: ви вже це підтвердили, або рушій обрав безпечний запасний варіант, що зберігає коректність. | Збірка успішна, результат записано. |
| **Error** | Ваші вимоги неможливо виконати без змін з вашого боку (занадто жорстке обмеження розміру, помилка розбору, недійсний ключ). | Ненульовий код виходу, **результат не записано**. |
| **Critical** | Помилка рушія. Жодні ваші дії цього не виправлять. | Ненульовий код виходу, результат не записано, завжди. [Надішліть звіт.](mailto:security@afterpack.dev) |

## Коди виходу

`npx afterpack@latest` повертає один із восьми кодів. Пишіть скрипти безпосередньо під них.

| Код | Значення |
|---|---|
| `0` | Успіх. Кожен зібраний файл обфусковано і записано. `--help` і `--version` також завершуються з кодом `0`. |
| `1` | Помилка. Нічого придатного не створено, а повідомлення в stderr називає, що сталося. |
| `2` | Частково. Зарезервовано для збірки з вичерпаною квотою; сьогодні жодна збірка його не повертає. |
| `3` | Обмеження розміру. Результат досяг би заданого вами [`inflation.max`](https://www.afterpack.dev/uk/docs/config#inflation-max) (`DIAG_SIZE_CAP_REACHED`). |
| `4` | Потрібен Pro. Запис [`regions`](https://www.afterpack.dev/uk/docs/config#regions) підвищує захист понад конфігурацію програми й потребує [`key`](https://www.afterpack.dev/uk/docs/config#key) (`DIAG_PRO_DIRECTIVE_REQUIRES_KEY`). CLI не читає директив із вихідного коду, тож до цього виходу веде лише `regions`. |
| `5` | Рефлексія. Виявлено патерн рефлексії під час виконання без [`reflection.allow`](https://www.afterpack.dev/uk/docs/config#reflection-allow) (`DIAG_REFLECTION_NOT_ACKNOWLEDGED`). |
| `6` | Потрібне оновлення. Хмарі AfterPack або цьому `afterpack` потрібен новіший `@afterpack/core`. Нічого не записано. |
| `64` | Неправильне використання. Невідомий прапорець або команда, некоректне значення або продубльований аргумент шляху. |

### Коли збірка завершується з кодом 64

Проблеми використання зупиняють запуск ще до його початку.

- Невідомий прапорець, невідома команда, некоректне значення або більше ніж один позиційний шлях. Рядок використання друкується повторно разом із помилкою.

### Коли збірка завершується з кодом 1

- Немає аргументу `<path>` і не знайдено результату збірки (`dist/`, `build/`, `out/`, `.output/`, `.next/` або каталог, у який за домовленістю пише бандлер, названий у `package.json`). AfterPack ніколи не читає власний файл конфігурації бандлера, тож нестандартний каталог виводу таким чином не визначається.
- Каталог збірки не існує або не містить файлів `.js`/`.mjs`/`.cjs`. Порожній каталог збірки завершує збірку помилкою. Зазвичай причина в тому, що вказано не той каталог або запуск відбувся до збірки.
- Файл повністю не вдалося обробити, або для непорожнього входу повернувся порожній результат.
- Файл, який рушій не може безпечно обфускувати. Збірка завершується помилкою і називає відповідні файли. Використовуйте [`paths.exclude`](https://www.afterpack.dev/uk/docs/config#paths-exclude), щоб виділити файл, який має вийти незмінним.
- Невдалий `verify` або невдале сканування `audit`.
- Будь-який код нижче з рівнем серйозності `Error` або `Critical`, крім `DIAG_SIZE_CAP_REACHED` (вихід `3`), `DIAG_PRO_DIRECTIVE_REQUIRES_KEY` (вихід `4`) і `DIAG_REFLECTION_NOT_ACKNOWLEDGED` (вихід `5`).

### Зупинка з помилкою (fail closed), без винятків

Збірка Pro або випускає захист рівня Pro, або не випускає нічого.

*(fail-closed request-flow diagram — see the web page)*

Щойно визначено [`key`](https://www.afterpack.dev/uk/docs/config#key), з [`AFTERPACK_key`](https://www.afterpack.dev/uk/docs/config#key) або з `afterpack.json`, збірка стає хмарною. Якщо хмарний виклик не вдався з будь-якої причини, рушій повертає помилку, і збірка завершується з кодом `1`, або `6`, коли хмарі потрібен новіший `@afterpack/core`. Вона не повертається до локальної збірки і не видає необфускований результат. Прапорця, який випускав би необфускований результат, немає. Зупинка збірки виносить проблему туди, де ви її побачите.

Цей контракт не залежить від способу виклику: `npx afterpack@latest` і автозапуск плагіна після закриття бандла поводяться однаково.

### Коди виходу в CI

```bash
npx afterpack@latest dist/ || {
  echo "AfterPack failed: nothing shipped. See the error above."
  exit 1
}
```

Ненульовий код зупиняє пайплайн. Причина з'являється в stderr і в кодах нижче.

## Повний довідник

### Рушій

| Код | Значення |
|---|---|
| `DIAG_TARGET_REACHED` | Info. Кожна частина файлу досягла запитаної [`complexity`](https://www.afterpack.dev/uk/docs/config#complexity). |
| `DIAG_TARGET_NOT_REACHED` | Починаючи з рушія 0.2.3, Error, і результат не записується: частина файлу не може досягти цільової [`complexity`](https://www.afterpack.dev/uk/docs/config#complexity) з дозволеними вами трансформаціями, бо [`transforms.scopeDeepen.enabled`](https://www.afterpack.dev/uk/docs/config#transforms-kind-enabled) має значення `false` або [директива ділянки](https://www.afterpack.dev/uk/docs/directives#what-you-can-set) обмежує ці рядки. Повідомлення називає файл і рядки. Увімкніть трансформацію знову, знизьте `complexity` для цього файлу чи ділянки або виключіть файл через [`paths.exclude`](https://www.afterpack.dev/uk/docs/config#paths-exclude). У рушії 0.2.2 це був Info: збірка постачала менш глибокий результат, а недобір через вимкнену трансформацію міг повідомлятися як `DIAG_TARGET_REACHED`. |
| `DIAG_INFLATION_BUDGET_HIT` | Info. Лише на збірці без floor зі скінченним [`inflation.max`](https://www.afterpack.dev/uk/docs/config#inflation-max): етап, що додає розмір, зупинився на цьому бюджеті, не досягнувши цілі. Результат коректний. Починаючи з рушія 0.2.3, floor рядкових констант ніколи не поступається бюджету, тож на збірці з floor цей код ніколи не з’являється і не означає, що рядковий літерал залишився читабельним. У рушії 0.2.2 явно заданий `inflation.max` міг перервати й кодування рядків; якщо ви його задавали, перезберіть проєкт на рушії 0.2.3. |
| `DIAG_SIZE_CAP_REACHED` | Error, код виходу `3`, і результат не записується: результат досяг би заданого вами [`inflation.max`](https://www.afterpack.dev/uk/docs/config#inflation-max). Починаючи з рушія 0.2.3, із цим лімітом звіряється й готовий файл, повідомлення називає обидва розміри в байтах, а кодування рядків ніколи не переривається, щоб вкластися в ліміт. Підвищте `inflation.max`, знизьте [`complexity`](https://www.afterpack.dev/uk/docs/config#complexity) або виключіть файл через [`paths.exclude`](https://www.afterpack.dev/uk/docs/config#paths-exclude). |
| `DIAG_SELF_INTEGRITY_INERT` | Error, починаючи з рушія 0.2.3, лише Pro, і результат не записується: [`transforms.selfIntegrity.enabled`](https://www.afterpack.dev/uk/docs/config#transforms-kind-enabled) увімкнено, але в збірці немає коду рівня `medium` або вище з увімкненим `transforms.crossDependency.enabled`, до якого можна прикріпити перевірку. Підніміть пресет або ділянку до `medium`, знову увімкніть `crossDependency` або вимкніть `selfIntegrity`. У рушії 0.2.2 така збірка завершувалася успішно без перевірки цілісності. |
| `DIAG_PATH_EXCLUDED` | Info. Файл відповів [`paths.exclude`](https://www.afterpack.dev/uk/docs/config#paths-exclude) і вийшов побайтово незмінним; його байти враховано як виключені користувачем. |
| `DIAG_DYNAMIC_SCOPE_NATIVE` | Info, починаючи з рушія 0.2.3. Інструкція `with` або прямий `eval` залишили області видимості навколо себе такими, як написано: імена в кожній охопній області видимості, аж до верхнього рівня файлу, зберігають оригінальне написання, а глобальні змінні всередині тіла `with` залишаються такими, як написано. Решта файлу обфускується як зазвичай. Щоб захистити ці імена, викликайте `eval` опосередковано, `(0, eval)(code)`, якщо виконуваному коду не потрібні локальні змінні, або винесіть код, якому потрібен `eval` чи `with`, в окремий файл. Див. [Семантичний контракт](https://www.afterpack.dev/uk/docs/semantic-contract#what-stays-as-you-wrote-it). |
| `DIAG_SURVIVING_READABLE_LITERAL` | Читабельних рядкових літералів залишилося більше, ніж дозволяє [`strings.leaks.max`](https://www.afterpack.dev/uk/docs/config#strings-leaks-max). Підвищте [`complexity`](https://www.afterpack.dev/uk/docs/config#complexity), знизьте [`strings.minLength`](https://www.afterpack.dev/uk/docs/config#strings-minLength) або підвищте ліміт. |
| `DIAG_SOURCE_MAP_INTEGRITY` | Info. Наданий вхідний `.map` не пройшов перевірку щодо свого входу, тож карту цього файлу відкидають, а обфускований код усе одно виходить. Відсутня карта нешкідлива; шкода, якої це уникає, — віддати хибну. |
| `DIAG_OUTPUT_UNPARSEABLE` | Error, і ознака помилки рушія. Повторний розбір результату не вдався, тож для цього файлу збірка завершується безпечно (fail closed): без коду, без карти джерел, без Protection Map. |
| `DIAG_PARSE_ERROR` | Error. Вхідний чанк не розібрався. AfterPack працює строго після збірки, на згенерованому JavaScript: спочатку скомпілюйте, потім вкажіть йому на JS-результат. |
| `DIAG_CONFIG_PARSE_ERROR` | Error. JSON [конфігурації рушія](https://www.afterpack.dev/uk/docs/config) не десеріалізувався. |
| `DIAG_PRO_DIRECTIVE_REQUIRES_KEY` | Error, вихід `4`, і результат не записується: збірка Free натрапила на [директиву ділянки](https://www.afterpack.dev/uk/docs/directives#free-builds), яка посилює захист понад конфігурацію програми. Задайте [`key`](https://www.afterpack.dev/uk/docs/config#key) або приберіть директиву. Починаючи з рушія 0.2.3, директива, яка лише послаблює захист, у Free ігнорується; рушій 0.2.2 відхиляв і таку. |
| `DIAG_INPUT_TOO_LARGE` | Один вхідний файл перевищив обмеження розміру. |
| `DIAG_BATCH_TOO_LARGE` | Пакет понад 500 MB загалом (413, без повторної спроби); збірка зупиняється з помилкою (fail closed). |
| `DIAG_INPUT_NESTING_EXCEEDS_ENVIRONMENT` | Error. Вхідні дані вкладені глибше, ніж парсер може безпечно обробити, — оцінюється ще до парсингу за межею 160 рівнів. Результат не записується. Зменшіть вкладеність вихідного коду. |
| `DIAG_OUTPUT_NESTING_EXCEEDS_ENVIRONMENT` | Error. Обфускований результат вкладався б глибше 400 рівнів — межі, яку браузери та Workers можуть безпечно розібрати. Результат не записується. Знизьте [`complexity`](https://www.afterpack.dev/uk/docs/config#complexity) для цього входу. |
| `DIAG_ENGINE_BUG_NO_PROGRESS` | Critical. Рушій не просунувся. Це помилка рушія. |
| `DIAG_ENGINE_BUG_NO_APPLICABLE_TRANSFORM` | Critical. Частина файлу залишилася нижче цільової складності, і жодна вимкнена трансформація чи директива ділянки цього не пояснює. Це помилка рушія. |
| `DIAG_ENGINE_BUG_PROCESS_THREAD_PANIC` | Critical. Робочий потік запанікував. Це помилка рушія. |

### Плагін збірки / CLI

| Код | Значення |
|---|---|
| `DIAG_DIRECTIVE_UNKNOWN` | Директива `@afterpack` назвала нерозпізнаний ключ. Звірте його з тим, [які ключі](https://www.afterpack.dev/uk/docs/directives#what-you-can-set) може перевизначати ділянка. |
| `DIAG_DIRECTIVE_UNSUPPORTED_FORM` | Цю форму маркера неможливо розмістити (рядковий коментар `// @afterpack …` або діапазон `@afterpack:begin/:end`). Використовуйте блокові маркери `/* @afterpack … */`. |
| `DIAG_DIRECTIVE_NOT_IMPLEMENTED` | У директиві записано ключ рівня всієї програми (наприклад, [`reflection.allow`](https://www.afterpack.dev/uk/docs/config#reflection-allow)) або надлишкову директиву на кшталт `skip=false`. Що насправді може перевизначати ділянка, див. у розділі [Які ключі](https://www.afterpack.dev/uk/docs/directives#what-you-can-set). |
| `DIAG_DIRECTIVE_SOURCE_UNRESOLVED` | Info. Директива стоїть у модулі, чию позицію не вдалося зіставити з результатом збірки, тож її не застосовано. Перенесіть позначений код в імпортований модуль. |
| `DIAG_DIRECTIVE_DANGLING_END` | [`/* @afterpack end */`](https://www.afterpack.dev/uk/docs/directives#what-you-can-set) без відкритого блоку над ним. |
| `DIAG_DIRECTIVE_REGION_TO_FILE` | [`identifiers.globals.rename`](https://www.afterpack.dev/uk/docs/config#identifiers-globals-rename) не можна обмежити ділянкою, тож директиву, яка його називає, проігноровано, і про це повідомлено. |
| `DIAG_DIRECTIVE_COVERAGE_UNVERIFIED` | Бандлований чанк із директивами не мав [source map, який можна декодувати](https://www.afterpack.dev/uk/docs/directives), тож позначені ділянки не вдалося знайти в його байтах. |
| `DIAG_DIRECTIVE_TARGET_ELIMINATED` | Директиви знайдено в map чанка, але вони не відповіли жодному діапазону. Позначений код видалено tree-shaking, або координати не збіглися. |
| `DIAG_ALREADY_OBFUSCATED` | Зібрані файли вже містять власний обфускований результат AfterPack від попереднього запуску, що встановлено зіставленням із [квитанцією захисту](https://www.afterpack.dev/uk/docs/cli#afterpack-verify-dir) за хешем вмісту. Результат AfterPack не ідемпотентний: спочатку перезберіть із вихідного коду. |
| `DIAG_AFTERPACK_DIR_IN_OUTPUT` | Помилка, і нічого не перезаписано. Усередині результату збірки є папка `.afterpack/`, де її резервні копії, квитанції та Protection Map потрапили б у розгортання. Видаліть її і зберіть знову. Див. [де лежить `.afterpack/`](https://www.afterpack.dev/uk/docs/cli#files). |
| `DIAG_RECEIPT_UNWRITABLE` | Помилка, і нічого не перезаписано. [Квитанцію захисту](https://www.afterpack.dev/uk/docs/cli#files) не вдається записати в `.afterpack/receipts/`. Зробіть цю папку доступною для запису і зберіть знову. |

### Хмарний API

| Код | Значення |
|---|---|
| `DIAG_INVALID_KEY` | Відсутній, некоректний або невідомий [`key`](https://www.afterpack.dev/uk/docs/config#key) (401). Перевірте [`AFTERPACK_key`](https://www.afterpack.dev/uk/docs/config#key) або випустіть новий ключ у [дашборді](https://www.afterpack.dev/uk/docs/dashboard/api-keys). |
| `DIAG_KEY_REVOKED` | API-ключ відкликано (401). |
| `DIAG_KEY_EXPIRED` | Термін дії API-ключа минув (401). |
| `DIAG_KEY_OUT_OF_SCOPE` | IP запиту поза дозволеним для ключа діапазоном (403). |
| `DIAG_MISSING_IP` | Запит не містив IP клієнта (400). |
| `DIAG_INVALID_MANIFEST` | Некоректне multipart-тіло або відсутня частина з маніфестом `batch`. |
| `DIAG_FILE_TOO_LARGE` | Один файл перевищив обмеження в байтах на файл (413). Розділіть його або виключіть через [`paths.exclude`](https://www.afterpack.dev/uk/docs/config#paths-exclude). |
| `DIAG_ENTITLEMENT_LAPSED` | Оплату підписки прострочено (402); оновіть платіжні дані, щоб і далі збирати. |
| `DIAG_QUOTA_EXHAUSTED` | Загальний обсяг байтів збірки перевищує [залишок ліміту](https://www.afterpack.dev/uk/docs/tiers), або досягнуто ліміту витрат на перевищення. Перевіряється один раз на збірку, до відправлення будь-якого файлу, тож нічого вже захищеного не погіршується. Поповніть баланс, перейдіть на вищий тариф або підвищте ліміт; помилка містить посилання. |
| `DIAG_RATE_LIMITED` | Перевищено ліміт частоти запитів (429); дотримуйтеся `Retry-After`. |
| `DIAG_RATE_CHECK_UNAVAILABLE` | Сама перевірка ліміту частоти не вдалася, тож запит зупиняється з помилкою (fail closed) (503); повторіть спробу. |
| `DIAG_BUILD_DEADLINE` | Бюджет реального часу вичерпався до того, як почалася обробка кожного файлу; незавершені файли названо. |
| `DIAG_ENGINE_FAILURE` | Хмарний рушій зазнав збою на файлі. |

### Рефлексія під час виконання

AfterPack виявляє такі шаблони [рефлексії під час виконання](https://www.afterpack.dev/uk/docs/config#reflection-allow): `functionToString`, `nameIntrospection`, `argumentsCallee`, `prototypeChain`, `decoratorMetadata` і `constructorIntrospection`. Кожне виявлення має код: підтверджена форма називає шаблон у коді, непідтверджена — це єдиний `DIAG_REFLECTION_NOT_ACKNOWLEDGED`, назву шаблону наведено в його повідомленні.

| Код | Значення |
|---|---|
| `DIAG_REFLECTION_nameIntrospection_ACKNOWLEDGED` | Info. Шаблон виявлено і збережено, бо ви його підтвердили. Один код на шаблон; назва посередині є будь-яким із наведених вище шаблонів. |
| `DIAG_REFLECTION_NOT_ACKNOWLEDGED` | Error, вихід `5`. Патерн рефлексії виявлено, і його **не** підтверджено, тож збірка зупиняється замість того, щоб випустити код, чиє читання під час виконання зламалося б; повідомлення називає патерн. Підтвердьте його через [`reflection.allow`](https://www.afterpack.dev/uk/docs/config#reflection-allow), який також приймає `angular` і `nestjs`, або виключіть файл через [`paths.exclude`](https://www.afterpack.dev/uk/docs/config#paths-exclude). |

> **Випадкові артефакти виявляє аудит**
>
> Випадковий [`.map`](https://www.afterpack.dev/uk/docs/config#sourceMap-enabled) або необфускований сусідній файл, що потрапив у дерево розгортання, виявляє [`npx afterpack@latest audit`](https://www.afterpack.dev/uk/docs/audit), а не збірка.
>
> Якщо код відсутній або описаний неправильно, створіть issue: [github.com/afterpack-dev/afterpack/issues](https://github.com/afterpack-dev/afterpack/issues).

Запустіть із [`--diagnostics.level=all`](https://www.afterpack.dev/uk/docs/config#diagnostics-level), щоб отримати повний потік діагностики для будь-якої збірки замість стандартного підсумку. У збірці через плагін той самий перемикач є параметром [`diagnostics.level`](https://www.afterpack.dev/uk/docs/config#diagnostics-level) або [`AFTERPACK_diagnostics_level`](https://www.afterpack.dev/uk/docs/config#diagnostics-level).

## Далі

- [Довідник CLI](https://www.afterpack.dev/uk/docs/cli): кожен прапорець, на який посилаються наведені вище коди.
- [Конфігурація](https://www.afterpack.dev/uk/docs/config): ключі конфігурації, на які посилаються ці коди.
- [Семантичний контракт](https://www.afterpack.dev/uk/docs/semantic-contract): що результат зберігає незмінним і кілька навмисних відмінностей.
- [Директиви](https://www.afterpack.dev/uk/docs/directives): повна граматика `@afterpack`, що стоїть за наведеними вище кодами директив.
- [Найкращі практики](https://www.afterpack.dev/uk/docs/best-practices): шаблони, що допомагають узагалі уникнути цих діагностик.
- [Тарифи](https://www.afterpack.dev/uk/docs/tiers): що є у Free, а що потребує [`key`](https://www.afterpack.dev/uk/docs/config#key).
