# Error codes

> Every build and validation problem code and every disko command error, each with a page.

A problem object looks like this; `code` is stable, `message` states the fix
and `docs` links to the code's page:

```json
{
  "code": "source_file_missing",
  "path": "src/main.ts",
  "line": 3,
  "column": 18,
  "message": "\"./rules.ts\" does not exist; create it or fix the path",
  "docs": "https://docs.disko.ooo/errors/source_file_missing"
}
```

`line` and `column` are 1-based and present only for source positions. A
build reports at most 100 problems.

## Build and validation problems

`disko publish`, the registry and room hosts report these codes in `problems`.

| Code | Meaning |
| --- | --- |
| [`archive_gzip_invalid`](/errors/archive_gzip_invalid) | The archive is not a valid gzip stream (header, deflate data, CRC or length). |
| [`archive_gzip_multi_member`](/errors/archive_gzip_multi_member) | The gzip stream contains more than one member. |
| [`archive_too_large`](/errors/archive_too_large) | The compressed archive exceeds 10 MiB. |
| [`archive_trailing_data`](/errors/archive_trailing_data) | Bytes follow the single gzip member. |
| [`asset_content_mismatch`](/errors/asset_content_mismatch) | An asset's bytes do not match the media type its extension selects. |
| [`asset_import_form`](/errors/asset_import_form) | An asset is imported or re-exported by a form other than its default binding. |
| [`digest_mismatch`](/errors/digest_mismatch) | The uncompressed tar does not hash to the expected release digest. |
| [`extension_unsupported`](/errors/extension_unsupported) | A file or import names an extension that is not allowed here. |
| [`file_too_large`](/errors/file_too_large) | One module exceeds 2 MiB or one asset exceeds 16 MiB. |
| [`file_unreachable`](/errors/file_unreachable) | An archive file is not reachable from the entry module through imports. |
| [`image_dimensions`](/errors/image_dimensions) | An image side is outside 1-4096 px. |
| [`import_attributes`](/errors/import_attributes) | An import or re-export carries import attributes (with or assert). |
| [`import_dynamic`](/errors/import_dynamic) | A module uses dynamic `import()`. |
| [`import_meta`](/errors/import_meta) | A module uses import.meta. |
| [`import_unresolved`](/errors/import_unresolved) | A relative import names a file that does not exist with exactly that path. |
| [`manifest_invalid`](/errors/manifest_invalid) | game.json is missing, too large, not valid JSON, or has a missing, unknown or invalid key. |
| [`manifest_not_canonical`](/errors/manifest_not_canonical) | The archive game.json differs from its canonical serialization. |
| [`module_encoding`](/errors/module_encoding) | A module is not UTF-8 or starts with a byte-order mark. |
| [`module_syntax`](/errors/module_syntax) | A module does not parse as an ECMAScript 2023 module. |
| [`modules_too_large`](/errors/modules_too_large) | All modules together exceed 8 MiB. |
| [`package_too_large`](/errors/package_too_large) | The uncompressed tar, headers included, exceeds 64 MiB. |
| [`path_case_conflict`](/errors/path_case_conflict) | Two file paths are equal after ASCII case-folding. |
| [`path_invalid`](/errors/path_invalid) | A file path breaks the package path grammar. |
| [`source_case_mismatch`](/errors/source_case_mismatch) | An import's case differs from the file name on disk. |
| [`source_file_missing`](/errors/source_file_missing) | A file named by game.json or an import does not exist in the project. |
| [`source_symlink`](/errors/source_symlink) | A project path on the import graph is a symbolic link. |
| [`specifier_escapes_root`](/errors/specifier_escapes_root) | A relative import climbs above the package root. |
| [`specifier_invalid`](/errors/specifier_invalid) | An import specifier is neither an exact relative path nor a disko: built-in name. |
| [`stdlib_module_unknown`](/errors/stdlib_module_unknown) | A disko: import names a module the host does not provide. |
| [`tar_header_not_canonical`](/errors/tar_header_not_canonical) | A tar header or its padding differs from the canonical ustar encoding. |
| [`tar_malformed`](/errors/tar_malformed) | The tar stream is truncated, has a wrong checksum, or has a missing or non-empty end marker. |
| [`tar_order`](/errors/tar_order) | Tar entries are not in strictly ascending path-byte order, or a path repeats. |
| [`too_many_assets`](/errors/too_many_assets) | The package contains more than 512 assets. |
| [`too_many_modules`](/errors/too_many_modules) | The package contains more than 512 modules. |
| [`top_level_await`](/errors/top_level_await) | A module uses await or for await outside any function. |
| [`ts_construct_unsupported`](/errors/ts_construct_unsupported) | A TypeScript file uses import = require, export =, a reference directive, or module/global augmentation. |
| [`ts_emit_conflict`](/errors/ts_emit_conflict) | Both a.ts and a.js exist, so emitting a.ts would overwrite a.js. |
| [`ts_type_error`](/errors/ts_type_error) | TypeScript type-checking reported an error. |

## Command errors

`disko` reports these codes as `error` in its `--json` output.

| Code | Exit code | Meaning |
| --- | --- | --- |
| [`api_unavailable`](/errors/api_unavailable) | 4 | disko-master could not be reached, or cannot create test rooms right now. |
| [`auth_unavailable`](/errors/auth_unavailable) | 4 | The sign-in service could not be reached or answered with an error, so `disko` could not sign you in. |
| [`build_failed`](/errors/build_failed) | 1 | The local build found problems; the output lists each one with its own code. |
| [`conflict`](/errors/conflict) | 5 | The registry refused the release with a conflict or rate-limit response; wait and try again. |
| [`credential_store_unavailable`](/errors/credential_store_unavailable) | 3 | No OS credential store is available, so `disko login --with-token` cannot save the token. |
| [`game_project_required`](/errors/game_project_required) | 2 | `disko dev` was run in a directory without `game.json`. |
| [`game_required`](/errors/game_required) | 1 | `game.json` has no `game` address, which a real publish needs. |
| [`internal_error`](/errors/internal_error) | 1 | `disko` hit an unexpected error that has no specific code. |
| [`invalid_package`](/errors/invalid_package) | 1 | The registry rejected the uploaded archive and listed the problems it found. |
| [`invalid_token`](/errors/invalid_token) | 3 | The value given as a CLI token is not a `dpt_` CLI token. |
| [`missing_permission`](/errors/missing_permission) | 3 | The CLI token lacks the permission the command needs, such as `publish` for the game or `test_rooms`. |
| [`not_found`](/errors/not_found) | 3 | The game does not exist, or the credential in use may not publish to it. |
| [`quota_exceeded`](/errors/quota_exceeded) | 5 | The account has used up a quota, such as publishes per 24 hours, stored release bytes or concurrent test rooms. |
| [`registry_error`](/errors/registry_error) | 1 | The registry refused the request with an error the CLI has no specific handling for. |
| [`registry_unavailable`](/errors/registry_unavailable) | 4 | The registry or disko-master could not be reached, or is temporarily unavailable. |
| [`sign_in_failed`](/errors/sign_in_failed) | 3 | Browser sign-in did not complete: it timed out, was canceled, or was rejected. |
| [`token_required`](/errors/token_required) | 2 | `disko login --with-token` read no token, because stdin is a terminal or is empty. |
| [`unauthorized`](/errors/unauthorized) | 3 | The credential was rejected: the token or sign-in is invalid, expired or revoked. |
| [`usage`](/errors/usage) | 2 | A command was run with an unknown, repeated, malformed or missing flag or argument. |
| [`version_exists`](/errors/version_exists) | 5 | This version is already published with a different archive or visibility; releases are immutable. |
| [`visibility_not_allowed`](/errors/visibility_not_allowed) | 2 | A private game accepts only private releases. |
| [`visibility_required`](/errors/visibility_required) | 2 | Publishing to a public game needs `--visibility`; there is no default. |
