Skip to main content

aube_codes/
errors.rs

1//! Error codes (`ERR_AUBE_*`).
2//!
3//! Each constant's *value* matches its identifier. The `ALL` slice
4//! is the registry — it gates the generated docs page
5//! (`docs/error-codes.md`, produced by the
6//! `generate-error-codes-docs` binary) and the self-tests in
7//! `lib.rs`. New codes go in both places: define a `pub const`,
8//! then add a [`crate::CodeMeta`] entry to `ALL` carrying the
9//! category, one-line description, and (optional) bespoke exit
10//! code.
11
12use crate::CodeMeta;
13
14// ── lockfile ─────────────────────────────────────────────────────────
15pub const ERR_AUBE_NO_LOCKFILE: &str = "ERR_AUBE_NO_LOCKFILE";
16pub const ERR_AUBE_LOCKFILE_PARSE: &str = "ERR_AUBE_LOCKFILE_PARSE";
17pub const ERR_AUBE_LOCKFILE_UNSUPPORTED_FORMAT: &str = "ERR_AUBE_LOCKFILE_UNSUPPORTED_FORMAT";
18pub const ERR_AUBE_RESOLUTION_SHAPE_MISMATCH: &str = "ERR_AUBE_RESOLUTION_SHAPE_MISMATCH";
19
20// ── resolver ─────────────────────────────────────────────────────────
21pub const ERR_AUBE_NO_MATCHING_VERSION: &str = "ERR_AUBE_NO_MATCHING_VERSION";
22pub const ERR_AUBE_NO_MATURE_MATCHING_VERSION: &str = "ERR_AUBE_NO_MATURE_MATCHING_VERSION";
23pub const ERR_AUBE_REGISTRY_ERROR: &str = "ERR_AUBE_REGISTRY_ERROR";
24pub const ERR_AUBE_UNKNOWN_CATALOG: &str = "ERR_AUBE_UNKNOWN_CATALOG";
25pub const ERR_AUBE_UNKNOWN_CATALOG_ENTRY: &str = "ERR_AUBE_UNKNOWN_CATALOG_ENTRY";
26pub const ERR_AUBE_BLOCKED_EXOTIC_SUBDEP: &str = "ERR_AUBE_BLOCKED_EXOTIC_SUBDEP";
27pub const ERR_AUBE_TRUST_DOWNGRADE: &str = "ERR_AUBE_TRUST_DOWNGRADE";
28pub const ERR_AUBE_TRUST_MISSING_TIME: &str = "ERR_AUBE_TRUST_MISSING_TIME";
29// `#[rustfmt::skip]` keeps the long names on a single visual line so the
30// declaration list reads as a flat table — rustfmt would otherwise wrap
31// to a `name: &str =\n    "name";` two-liner for any const past col 100.
32#[rustfmt::skip] pub const ERR_AUBE_TRUST_EXCLUDE_INVALID_VERSION_UNION: &str = "ERR_AUBE_TRUST_EXCLUDE_INVALID_VERSION_UNION";
33#[rustfmt::skip] pub const ERR_AUBE_TRUST_EXCLUDE_NAME_GLOB_WITH_VERSIONS: &str = "ERR_AUBE_TRUST_EXCLUDE_NAME_GLOB_WITH_VERSIONS";
34pub const ERR_AUBE_PEER_CONTEXT_NOT_CONVERGED: &str = "ERR_AUBE_PEER_CONTEXT_NOT_CONVERGED";
35
36// ── registry / network ──────────────────────────────────────────────
37pub const ERR_AUBE_PACKAGE_NOT_FOUND: &str = "ERR_AUBE_PACKAGE_NOT_FOUND";
38pub const ERR_AUBE_ACCESS_ENTITY_NOT_FOUND: &str = "ERR_AUBE_ACCESS_ENTITY_NOT_FOUND";
39pub const ERR_AUBE_VERSION_NOT_FOUND: &str = "ERR_AUBE_VERSION_NOT_FOUND";
40pub const ERR_AUBE_UNAUTHORIZED: &str = "ERR_AUBE_UNAUTHORIZED";
41pub const ERR_AUBE_OFFLINE: &str = "ERR_AUBE_OFFLINE";
42pub const ERR_AUBE_INVALID_PACKAGE_NAME: &str = "ERR_AUBE_INVALID_PACKAGE_NAME";
43pub const ERR_AUBE_REGISTRY_WRITE_REJECTED: &str = "ERR_AUBE_REGISTRY_WRITE_REJECTED";
44pub const ERR_AUBE_MALICIOUS_PACKAGE: &str = "ERR_AUBE_MALICIOUS_PACKAGE";
45pub const ERR_AUBE_LOW_DOWNLOAD_PACKAGE: &str = "ERR_AUBE_LOW_DOWNLOAD_PACKAGE";
46pub const ERR_AUBE_ADVISORY_CHECK_FAILED: &str = "ERR_AUBE_ADVISORY_CHECK_FAILED";
47pub const ERR_AUBE_SECURITY_SCANNER_FATAL: &str = "ERR_AUBE_SECURITY_SCANNER_FATAL";
48pub const ERR_AUBE_SECURITY_SCANNER_FAILED: &str = "ERR_AUBE_SECURITY_SCANNER_FAILED";
49pub const ERR_AUBE_WEB_LOGIN_RESPONSE_TOO_LARGE: &str = "ERR_AUBE_WEB_LOGIN_RESPONSE_TOO_LARGE";
50
51// ── tarball / store ─────────────────────────────────────────────────
52pub const ERR_AUBE_TARBALL_INTEGRITY: &str = "ERR_AUBE_TARBALL_INTEGRITY";
53pub const ERR_AUBE_TARBALL_EXTRACT: &str = "ERR_AUBE_TARBALL_EXTRACT";
54pub const ERR_AUBE_PKG_CONTENT_MISMATCH: &str = "ERR_AUBE_PKG_CONTENT_MISMATCH";
55pub const ERR_AUBE_TARBALL_URL_MISMATCH: &str = "ERR_AUBE_TARBALL_URL_MISMATCH";
56pub const ERR_AUBE_NO_HOME: &str = "ERR_AUBE_NO_HOME";
57pub const ERR_AUBE_GIT_ERROR: &str = "ERR_AUBE_GIT_ERROR";
58
59// ── linker ──────────────────────────────────────────────────────────
60pub const ERR_AUBE_LINK_FAILED: &str = "ERR_AUBE_LINK_FAILED";
61pub const ERR_AUBE_PATCH_FAILED: &str = "ERR_AUBE_PATCH_FAILED";
62pub const ERR_AUBE_MISSING_PACKAGE_INDEX: &str = "ERR_AUBE_MISSING_PACKAGE_INDEX";
63pub const ERR_AUBE_UNSAFE_INDEX_KEY: &str = "ERR_AUBE_UNSAFE_INDEX_KEY";
64pub const ERR_AUBE_UNSAFE_PACKAGE_NAME: &str = "ERR_AUBE_UNSAFE_PACKAGE_NAME";
65pub const ERR_AUBE_MISSING_STORE_FILE: &str = "ERR_AUBE_MISSING_STORE_FILE";
66
67// ── scripts ─────────────────────────────────────────────────────────
68pub const ERR_AUBE_SCRIPT_SPAWN: &str = "ERR_AUBE_SCRIPT_SPAWN";
69pub const ERR_AUBE_SCRIPT_NON_ZERO_EXIT: &str = "ERR_AUBE_SCRIPT_NON_ZERO_EXIT";
70#[rustfmt::skip] pub const ERR_AUBE_BUILD_POLICY_UNSUPPORTED_VALUE: &str = "ERR_AUBE_BUILD_POLICY_UNSUPPORTED_VALUE";
71#[rustfmt::skip] pub const ERR_AUBE_BUILD_POLICY_INVALID_VERSION_UNION: &str = "ERR_AUBE_BUILD_POLICY_INVALID_VERSION_UNION";
72#[rustfmt::skip] pub const ERR_AUBE_BUILD_POLICY_WILDCARD_WITH_VERSION: &str = "ERR_AUBE_BUILD_POLICY_WILDCARD_WITH_VERSION";
73
74// ── workspace / filter ──────────────────────────────────────────────
75pub const ERR_AUBE_WORKSPACE_PARSE: &str = "ERR_AUBE_WORKSPACE_PARSE";
76pub const ERR_AUBE_FILTER_EMPTY: &str = "ERR_AUBE_FILTER_EMPTY";
77pub const ERR_AUBE_FILTER_GIT_IO: &str = "ERR_AUBE_FILTER_GIT_IO";
78pub const ERR_AUBE_FILTER_GIT_FAILED: &str = "ERR_AUBE_FILTER_GIT_FAILED";
79
80// ── manifest ────────────────────────────────────────────────────────
81pub const ERR_AUBE_MANIFEST_PARSE: &str = "ERR_AUBE_MANIFEST_PARSE";
82pub const ERR_AUBE_MANIFEST_YAML_PARSE: &str = "ERR_AUBE_MANIFEST_YAML_PARSE";
83
84// ── engine / cli ────────────────────────────────────────────────────
85pub const ERR_AUBE_UNSUPPORTED_ENGINE: &str = "ERR_AUBE_UNSUPPORTED_ENGINE";
86pub const ERR_AUBE_RECURSIVE_NOT_SUPPORTED: &str = "ERR_AUBE_RECURSIVE_NOT_SUPPORTED";
87pub const ERR_AUBE_UNKNOWN_COMMAND: &str = "ERR_AUBE_UNKNOWN_COMMAND";
88pub const ERR_AUBE_NPM_ONLY_COMMAND: &str = "ERR_AUBE_NPM_ONLY_COMMAND";
89pub const ERR_AUBE_COMPLETION_FAILED: &str = "ERR_AUBE_COMPLETION_FAILED";
90pub const ERR_AUBE_USAGE_SPEC_WRITE_FAILED: &str = "ERR_AUBE_USAGE_SPEC_WRITE_FAILED";
91pub const ERR_AUBE_REMOVE_PRIOR_INSTALL_DIR: &str = "ERR_AUBE_REMOVE_PRIOR_INSTALL_DIR";
92pub const ERR_AUBE_CONFIG_NESTED_AUBE_KEY: &str = "ERR_AUBE_CONFIG_NESTED_AUBE_KEY";
93pub const ERR_AUBE_CONFLICTING_BUILD_FLAGS: &str = "ERR_AUBE_CONFLICTING_BUILD_FLAGS";
94pub const ERR_AUBE_ACCESS_INVALID_ARGUMENT: &str = "ERR_AUBE_ACCESS_INVALID_ARGUMENT";
95pub const ERR_AUBE_SHIM_CREATE_FAILED: &str = "ERR_AUBE_SHIM_CREATE_FAILED";
96pub const ERR_AUBE_SHIM_EXEC_FAILED: &str = "ERR_AUBE_SHIM_EXEC_FAILED";
97
98// ── node runtime (devEngines.runtime / .node-version / .nvmrc) ──────
99#[rustfmt::skip] pub const ERR_AUBE_RUNTIME_VERSION_UNSATISFIED: &str = "ERR_AUBE_RUNTIME_VERSION_UNSATISFIED";
100#[rustfmt::skip] pub const ERR_AUBE_RUNTIME_NO_MATCHING_VERSION: &str = "ERR_AUBE_RUNTIME_NO_MATCHING_VERSION";
101pub const ERR_AUBE_RUNTIME_DOWNLOAD_FAILED: &str = "ERR_AUBE_RUNTIME_DOWNLOAD_FAILED";
102#[rustfmt::skip] pub const ERR_AUBE_RUNTIME_CHECKSUM_MISMATCH: &str = "ERR_AUBE_RUNTIME_CHECKSUM_MISMATCH";
103pub const ERR_AUBE_RUNTIME_EXTRACT_FAILED: &str = "ERR_AUBE_RUNTIME_EXTRACT_FAILED";
104#[rustfmt::skip] pub const ERR_AUBE_RUNTIME_MISE_INSTALL_FAILED: &str = "ERR_AUBE_RUNTIME_MISE_INSTALL_FAILED";
105#[rustfmt::skip] pub const ERR_AUBE_RUNTIME_UNSUPPORTED_PLATFORM: &str = "ERR_AUBE_RUNTIME_UNSUPPORTED_PLATFORM";
106pub const ERR_AUBE_RUNTIME_IO: &str = "ERR_AUBE_RUNTIME_IO";
107#[rustfmt::skip] pub const ERR_AUBE_SELF_UPDATE_UNSUPPORTED_PLATFORM: &str = "ERR_AUBE_SELF_UPDATE_UNSUPPORTED_PLATFORM";
108
109// ── misc / safety ──────────────────────────────────────────────────
110pub const ERR_AUBE_INSTALL_CANCELLED: &str = "ERR_AUBE_INSTALL_CANCELLED";
111pub const ERR_AUBE_PATCHES_TRACKING_WRITE: &str = "ERR_AUBE_PATCHES_TRACKING_WRITE";
112pub const ERR_AUBE_UNSAFE_SHEBANG_INTERPRETER: &str = "ERR_AUBE_UNSAFE_SHEBANG_INTERPRETER";
113pub const ERR_AUBE_EMBED_INVALID_PROJECT: &str = "ERR_AUBE_EMBED_INVALID_PROJECT";
114pub const ERR_AUBE_EMBED_INSTALL_FAILED: &str = "ERR_AUBE_EMBED_INSTALL_FAILED";
115pub const ERR_AUBE_EMBED_INVALID_SETTING: &str = "ERR_AUBE_EMBED_INVALID_SETTING";
116pub const ERR_AUBE_EMBED_ALREADY_INITIALIZED: &str = "ERR_AUBE_EMBED_ALREADY_INITIALIZED";
117pub const ERR_AUBE_FFI_INVALID_ARGUMENT: &str = "ERR_AUBE_FFI_INVALID_ARGUMENT";
118pub const ERR_AUBE_FFI_UNKNOWN_HANDLE: &str = "ERR_AUBE_FFI_UNKNOWN_HANDLE";
119pub const ERR_AUBE_FFI_RUNTIME: &str = "ERR_AUBE_FFI_RUNTIME";
120pub const ERR_AUBE_FFI_PANIC: &str = "ERR_AUBE_FFI_PANIC";
121
122/// Stable category labels that group codes in the generated docs and
123/// in `EXIT_TABLE`'s 10-wide allocation ranges. Public so the docs
124/// generator can iterate them in a deterministic order.
125pub mod category {
126    pub const LOCKFILE: &str = "Lockfile";
127    pub const RESOLVER: &str = "Resolver";
128    pub const TARBALL_STORE: &str = "Tarball / store";
129    pub const REGISTRY_NETWORK: &str = "Registry / network";
130    pub const SCRIPTS: &str = "Scripts / build";
131    pub const LINKER: &str = "Linker";
132    pub const MANIFEST_WORKSPACE: &str = "Manifest / workspace";
133    pub const ENGINE_CLI: &str = "Engine / CLI";
134    pub const MISC_SAFETY: &str = "Misc / safety";
135    /// Add-time / install-time supply-chain policy errors. Paired
136    /// with [`crate::warnings::category::SUPPLY_CHAIN`].
137    pub const SUPPLY_CHAIN: &str = "Supply chain (add-time)";
138}
139
140/// Registry of every error code with its category, description, and
141/// (optional) bespoke exit code. Walked by the
142/// `generate-error-codes-docs` binary and by the self-tests in
143/// `lib.rs` and `exit.rs`. New codes must be added here.
144pub const ALL: &[CodeMeta] = &[
145    // Lockfile
146    CodeMeta {
147        name: ERR_AUBE_NO_LOCKFILE,
148        category: category::LOCKFILE,
149        description: "An operation that required a lockfile (`--frozen-lockfile`, `aube fetch`, etc.) found none in the project.",
150        exit_code: Some(10),
151    },
152    CodeMeta {
153        name: ERR_AUBE_LOCKFILE_PARSE,
154        category: category::LOCKFILE,
155        description: "Lockfile is structurally invalid — version guard failed, YAML shape is wrong, or `yaml_serde` couldn't round-trip the contents.",
156        exit_code: Some(11),
157    },
158    CodeMeta {
159        name: ERR_AUBE_LOCKFILE_UNSUPPORTED_FORMAT,
160        category: category::LOCKFILE,
161        description: "Lockfile filename was recognized but its format isn't supported on this aube version.",
162        exit_code: Some(12),
163    },
164    CodeMeta {
165        name: ERR_AUBE_RESOLUTION_SHAPE_MISMATCH,
166        category: category::LOCKFILE,
167        description: "A registry-style lockfile dependency path is backed by a git, local directory, or direct tarball resolution.",
168        exit_code: Some(13),
169    },
170    // Resolver
171    CodeMeta {
172        name: ERR_AUBE_NO_MATCHING_VERSION,
173        category: category::RESOLVER,
174        description: "No published version of the named package satisfies the requested range.",
175        exit_code: Some(20),
176    },
177    CodeMeta {
178        name: ERR_AUBE_NO_MATURE_MATCHING_VERSION,
179        category: category::RESOLVER,
180        description: "A version satisfying the range exists but every candidate was younger than `minimumReleaseAge` and `minimumReleaseAgeStrict=true`.",
181        exit_code: Some(21),
182    },
183    CodeMeta {
184        name: ERR_AUBE_BLOCKED_EXOTIC_SUBDEP,
185        category: category::RESOLVER,
186        description: "Transitive dep used a `git:` / `file:` / `tarball` specifier and `blockExoticSubdeps=true`.",
187        exit_code: Some(22),
188    },
189    CodeMeta {
190        name: ERR_AUBE_TRUST_DOWNGRADE,
191        category: category::RESOLVER,
192        description: "Picked version dropped trust evidence the prior version had (`trustPolicy=no-downgrade`).",
193        exit_code: Some(23),
194    },
195    CodeMeta {
196        name: ERR_AUBE_TRUST_MISSING_TIME,
197        category: category::RESOLVER,
198        description: "Registry's packument has no `time` entry for the picked version (`trustPolicy=no-downgrade`).",
199        exit_code: Some(24),
200    },
201    CodeMeta {
202        name: ERR_AUBE_UNKNOWN_CATALOG,
203        category: category::RESOLVER,
204        description: "A `catalog:<name>` reference was used but the catalog isn't defined.",
205        exit_code: Some(25),
206    },
207    CodeMeta {
208        name: ERR_AUBE_UNKNOWN_CATALOG_ENTRY,
209        category: category::RESOLVER,
210        description: "The catalog exists but has no entry for the requested package.",
211        exit_code: Some(26),
212    },
213    CodeMeta {
214        name: ERR_AUBE_PEER_CONTEXT_NOT_CONVERGED,
215        category: category::RESOLVER,
216        description: "Peer-context fixed-point loop hit `MAX_ITERATIONS=16` without converging — usually mutually-recursive peers.",
217        exit_code: Some(27),
218    },
219    CodeMeta {
220        name: ERR_AUBE_REGISTRY_ERROR,
221        category: category::RESOLVER,
222        description: "Generic registry error from inside the resolver.",
223        exit_code: None,
224    },
225    CodeMeta {
226        name: ERR_AUBE_TRUST_EXCLUDE_INVALID_VERSION_UNION,
227        category: category::RESOLVER,
228        description: "A `trustPolicyExclude` pattern had an invalid semver range.",
229        exit_code: None,
230    },
231    CodeMeta {
232        name: ERR_AUBE_TRUST_EXCLUDE_NAME_GLOB_WITH_VERSIONS,
233        category: category::RESOLVER,
234        description: "A `trustPolicyExclude` pattern combined a name glob with versions.",
235        exit_code: None,
236    },
237    // Tarball / store
238    CodeMeta {
239        name: ERR_AUBE_TARBALL_INTEGRITY,
240        category: category::TARBALL_STORE,
241        description: "Downloaded tarball's hash didn't match the lockfile's / packument's `dist.integrity`.",
242        exit_code: Some(30),
243    },
244    CodeMeta {
245        name: ERR_AUBE_TARBALL_EXTRACT,
246        category: category::TARBALL_STORE,
247        description: "Tarball couldn't be extracted (corrupt gzip, unexpected entry shape, etc.).",
248        exit_code: Some(31),
249    },
250    CodeMeta {
251        name: ERR_AUBE_PKG_CONTENT_MISMATCH,
252        category: category::TARBALL_STORE,
253        description: "Tarball's `package.json` declared a different `(name, version)` than the resolver expected (`strictStorePkgContentCheck=true`).",
254        exit_code: Some(32),
255    },
256    CodeMeta {
257        name: ERR_AUBE_GIT_ERROR,
258        category: category::TARBALL_STORE,
259        description: "Git operation failed during a `git:` dep prepare or checkout.",
260        exit_code: Some(33),
261    },
262    CodeMeta {
263        name: ERR_AUBE_TARBALL_URL_MISMATCH,
264        category: category::TARBALL_STORE,
265        description: "A registry lockfile entry's explicit tarball URL didn't match the registry metadata for that `(name, version)`.",
266        exit_code: Some(34),
267    },
268    CodeMeta {
269        name: ERR_AUBE_NO_HOME,
270        category: category::TARBALL_STORE,
271        description: "`HOME` (or platform equivalent) is unset, so aube can't locate its store.",
272        exit_code: None,
273    },
274    // Registry / network
275    CodeMeta {
276        name: ERR_AUBE_PACKAGE_NOT_FOUND,
277        category: category::REGISTRY_NETWORK,
278        description: "Registry returned 404 for the package name.",
279        exit_code: Some(40),
280    },
281    CodeMeta {
282        name: ERR_AUBE_ACCESS_ENTITY_NOT_FOUND,
283        category: category::REGISTRY_NETWORK,
284        description: "Registry returned 404 for an access user, organization, or team.",
285        exit_code: None,
286    },
287    CodeMeta {
288        name: ERR_AUBE_VERSION_NOT_FOUND,
289        category: category::REGISTRY_NETWORK,
290        description: "Package exists but the requested version doesn't.",
291        exit_code: Some(41),
292    },
293    CodeMeta {
294        name: ERR_AUBE_UNAUTHORIZED,
295        category: category::REGISTRY_NETWORK,
296        description: "Registry returned 401/403 — missing or invalid auth. Run `aube login`.",
297        exit_code: Some(42),
298    },
299    CodeMeta {
300        name: ERR_AUBE_WEB_LOGIN_RESPONSE_TOO_LARGE,
301        category: category::REGISTRY_NETWORK,
302        description: "The web-login token response exceeded the 64 KiB safety limit.",
303        exit_code: None,
304    },
305    CodeMeta {
306        name: ERR_AUBE_OFFLINE,
307        category: category::REGISTRY_NETWORK,
308        description: "Offline mode and the requested resource isn't in the local cache.",
309        exit_code: Some(43),
310    },
311    CodeMeta {
312        name: ERR_AUBE_INVALID_PACKAGE_NAME,
313        category: category::REGISTRY_NETWORK,
314        description: "A name doesn't match npm's grammar — rejected before any I/O so a hostile manifest can't use the cache-path builder as a write primitive.",
315        exit_code: Some(44),
316    },
317    CodeMeta {
318        name: ERR_AUBE_REGISTRY_WRITE_REJECTED,
319        category: category::REGISTRY_NETWORK,
320        description: "Registry rejected a publish/deprecate/owner write with a non-2xx response.",
321        exit_code: Some(45),
322    },
323    CodeMeta {
324        name: ERR_AUBE_MALICIOUS_PACKAGE,
325        category: category::REGISTRY_NETWORK,
326        description: "`aube add` refused a package because OSV reports it as malicious (`MAL-*` advisory). Hard block — confirmed-malicious advisories aren't a judgement call.",
327        exit_code: Some(46),
328    },
329    CodeMeta {
330        name: ERR_AUBE_LOW_DOWNLOAD_PACKAGE,
331        category: category::REGISTRY_NETWORK,
332        description: "`aube add` refused a package whose weekly downloads fall below `lowDownloadThreshold` in a non-interactive context (or when stdin is not a TTY). Pass `--allow-low-downloads` to bypass.",
333        exit_code: Some(47),
334    },
335    CodeMeta {
336        name: ERR_AUBE_ADVISORY_CHECK_FAILED,
337        category: category::REGISTRY_NETWORK,
338        description: "`aube add` couldn't reach the OSV advisory API and `advisoryCheck = required` is set. Distinct from `ERR_AUBE_MALICIOUS_PACKAGE` so CI tooling can tell a network outage from a confirmed malicious advisory.",
339        exit_code: Some(49),
340    },
341    CodeMeta {
342        name: ERR_AUBE_SECURITY_SCANNER_FATAL,
343        category: category::SUPPLY_CHAIN,
344        description: "User-configured `securityScanner` returned a `fatal`-level advisory against a package the user is trying to add. Bun-style pluggable scanner contract; the scanner itself decides what counts as fatal.",
345        exit_code: Some(48),
346    },
347    CodeMeta {
348        name: ERR_AUBE_SECURITY_SCANNER_FAILED,
349        category: category::SUPPLY_CHAIN,
350        description: "User-configured `securityScanner` couldn't be spawned, exited non-zero, timed out, or emitted unparseable JSON. Fail-closed by design: a configured scanner that can't run is treated as a refusal, not a free pass. Set `securityScanner = \"\"` to disable the integration when bootstrapping or recovering from a broken scanner.",
351        exit_code: None,
352    },
353    // Scripts / build
354    CodeMeta {
355        name: ERR_AUBE_SCRIPT_NON_ZERO_EXIT,
356        category: category::SCRIPTS,
357        description: "A lifecycle script (`preinstall` / `install` / `postinstall` / a `package.json` script) exited non-zero.",
358        exit_code: Some(50),
359    },
360    CodeMeta {
361        name: ERR_AUBE_SCRIPT_SPAWN,
362        category: category::SCRIPTS,
363        description: "Couldn't spawn a script's interpreter (shell missing, jail setup failed, etc.).",
364        exit_code: Some(51),
365    },
366    CodeMeta {
367        name: ERR_AUBE_BUILD_POLICY_UNSUPPORTED_VALUE,
368        category: category::SCRIPTS,
369        description: "An entry in `allowBuilds` had a value that wasn't `true`/`false`.",
370        exit_code: None,
371    },
372    CodeMeta {
373        name: ERR_AUBE_BUILD_POLICY_INVALID_VERSION_UNION,
374        category: category::SCRIPTS,
375        description: "An `allowBuilds` pattern's version union was unparseable.",
376        exit_code: None,
377    },
378    CodeMeta {
379        name: ERR_AUBE_BUILD_POLICY_WILDCARD_WITH_VERSION,
380        category: category::SCRIPTS,
381        description: "An `allowBuilds` pattern combined a wildcard name with a version union.",
382        exit_code: None,
383    },
384    // Linker
385    CodeMeta {
386        name: ERR_AUBE_PATCH_FAILED,
387        category: category::LINKER,
388        description: "Applying a `pnpm.patchedDependencies` patch failed.",
389        exit_code: Some(60),
390    },
391    CodeMeta {
392        name: ERR_AUBE_LINK_FAILED,
393        category: category::LINKER,
394        description: "Symlink / junction / hardlink couldn't be created — usually permissions or filesystem support.",
395        exit_code: Some(61),
396    },
397    CodeMeta {
398        name: ERR_AUBE_MISSING_PACKAGE_INDEX,
399        category: category::LINKER,
400        description: "Internal: a caller skipped `load_index` but the package wasn't already materialized.",
401        exit_code: Some(62),
402    },
403    CodeMeta {
404        name: ERR_AUBE_MISSING_STORE_FILE,
405        category: category::LINKER,
406        description: "A package index references a CAS shard that doesn't exist on disk. Re-run install to re-fetch.",
407        exit_code: Some(63),
408    },
409    // Manifest / workspace
410    CodeMeta {
411        name: ERR_AUBE_MANIFEST_PARSE,
412        category: category::MANIFEST_WORKSPACE,
413        description: "A `package.json` had a syntax error. miette renders a pointer at the offending byte.",
414        exit_code: Some(70),
415    },
416    CodeMeta {
417        name: ERR_AUBE_WORKSPACE_PARSE,
418        category: category::MANIFEST_WORKSPACE,
419        description: "An `aube-workspace.yaml` / `pnpm-workspace.yaml` was structurally invalid.",
420        exit_code: Some(71),
421    },
422    CodeMeta {
423        name: ERR_AUBE_MANIFEST_YAML_PARSE,
424        category: category::MANIFEST_WORKSPACE,
425        description: "A workspace YAML helper file was structurally invalid (no source pointer available).",
426        exit_code: None,
427    },
428    CodeMeta {
429        name: ERR_AUBE_FILTER_EMPTY,
430        category: category::MANIFEST_WORKSPACE,
431        description: "`--filter` was passed an empty selector.",
432        exit_code: None,
433    },
434    CodeMeta {
435        name: ERR_AUBE_FILTER_GIT_IO,
436        category: category::MANIFEST_WORKSPACE,
437        description: "A `--filter ...[ref]` selector failed to spawn `git`.",
438        exit_code: None,
439    },
440    CodeMeta {
441        name: ERR_AUBE_FILTER_GIT_FAILED,
442        category: category::MANIFEST_WORKSPACE,
443        description: "The git subprocess for a `--filter ...[ref]` selector exited non-zero.",
444        exit_code: None,
445    },
446    // Engine / CLI
447    CodeMeta {
448        name: ERR_AUBE_UNSUPPORTED_ENGINE,
449        category: category::ENGINE_CLI,
450        description: "One or more packages declared an `engines` constraint incompatible with the running Node/aube and `engine-strict=true`.",
451        exit_code: Some(80),
452    },
453    CodeMeta {
454        name: ERR_AUBE_UNKNOWN_COMMAND,
455        category: category::ENGINE_CLI,
456        description: "The named subcommand isn't a built-in aube command and isn't a script in the manifest.",
457        exit_code: Some(81),
458    },
459    CodeMeta {
460        name: ERR_AUBE_NPM_ONLY_COMMAND,
461        category: category::ENGINE_CLI,
462        description: "The user invoked an npm-only command (`whoami`, `token`, `owner`, `search`, `pkg`, `set-script`) — aube doesn't implement these; use npm.",
463        exit_code: Some(82),
464    },
465    CodeMeta {
466        name: ERR_AUBE_RECURSIVE_NOT_SUPPORTED,
467        category: category::ENGINE_CLI,
468        description: "A command was invoked under `--recursive` but doesn't support recursive execution.",
469        exit_code: None,
470    },
471    CodeMeta {
472        name: ERR_AUBE_COMPLETION_FAILED,
473        category: category::ENGINE_CLI,
474        description: "`aube completion` couldn't invoke `usage` to render the shell completions.",
475        exit_code: None,
476    },
477    CodeMeta {
478        name: ERR_AUBE_USAGE_SPEC_WRITE_FAILED,
479        category: category::ENGINE_CLI,
480        description: "`aube usage` couldn't write the CLI spec to stdout; the output would have been truncated.",
481        exit_code: None,
482    },
483    CodeMeta {
484        name: ERR_AUBE_REMOVE_PRIOR_INSTALL_DIR,
485        category: category::ENGINE_CLI,
486        description: "Couldn't clean up a prior global install dir before re-installing.",
487        exit_code: None,
488    },
489    CodeMeta {
490        name: ERR_AUBE_CONFIG_NESTED_AUBE_KEY,
491        category: category::ENGINE_CLI,
492        description: "`aube config set <prefix>.<sub> …` was used for a key whose prefix is an aube map setting (e.g. `allowBuilds.<pkg>`). Such nested writes would otherwise land in `.npmrc` where aube doesn't read them and npm warns/errors about the unknown key — set the map in workspace yaml or `package.json#aube.<prefix>` instead.",
493        exit_code: None,
494    },
495    CodeMeta {
496        name: ERR_AUBE_CONFLICTING_BUILD_FLAGS,
497        category: category::ENGINE_CLI,
498        description: "`aube add` was passed the same package name in both `--allow-build` and `--deny-build`.",
499        exit_code: None,
500    },
501    CodeMeta {
502        name: ERR_AUBE_ACCESS_INVALID_ARGUMENT,
503        category: category::ENGINE_CLI,
504        description: "`aube access` received an invalid access setting, permission level, team, or package argument.",
505        exit_code: None,
506    },
507    CodeMeta {
508        name: ERR_AUBE_SHIM_CREATE_FAILED,
509        category: category::ENGINE_CLI,
510        description: "`aube activate <shell>` couldn't create or refresh an executable shim in aube's shim directory.",
511        exit_code: None,
512    },
513    CodeMeta {
514        name: ERR_AUBE_SHIM_EXEC_FAILED,
515        category: category::ENGINE_CLI,
516        description: "A runtime tool shim resolved its target but couldn't exec or spawn the selected tool.",
517        exit_code: None,
518    },
519    // Node runtime (devEngines.runtime / .node-version / .nvmrc)
520    CodeMeta {
521        name: ERR_AUBE_RUNTIME_VERSION_UNSATISFIED,
522        category: category::ENGINE_CLI,
523        description: "The project requires a Node.js version that isn't available and policy forbids fetching it (`devEngines.runtime` with `onFail: \"error\"`, `runtimeOnFail=error`, or offline mode with nothing installed).",
524        exit_code: Some(83),
525    },
526    CodeMeta {
527        name: ERR_AUBE_RUNTIME_NO_MATCHING_VERSION,
528        category: category::ENGINE_CLI,
529        description: "No Node.js release in the dist index satisfies the requested version (bad range, unknown LTS codename, or no build for this platform).",
530        exit_code: Some(84),
531    },
532    CodeMeta {
533        name: ERR_AUBE_RUNTIME_DOWNLOAD_FAILED,
534        category: category::ENGINE_CLI,
535        description: "Fetching the Node.js dist index, checksum file, or release archive failed after retries.",
536        exit_code: Some(85),
537    },
538    CodeMeta {
539        name: ERR_AUBE_RUNTIME_CHECKSUM_MISMATCH,
540        category: category::ENGINE_CLI,
541        description: "A downloaded Node.js archive's SHA-256 didn't match the lockfile pin or `SHASUMS256.txt`. The archive is discarded and never retried automatically.",
542        exit_code: Some(86),
543    },
544    CodeMeta {
545        name: ERR_AUBE_RUNTIME_EXTRACT_FAILED,
546        category: category::ENGINE_CLI,
547        description: "A Node.js release archive was corrupt or contained unsafe entry paths.",
548        exit_code: Some(87),
549    },
550    CodeMeta {
551        name: ERR_AUBE_RUNTIME_MISE_INSTALL_FAILED,
552        category: category::ENGINE_CLI,
553        description: "Delegating a Node.js install to mise failed — `mise install node@<version>` exited non-zero or the install wasn't discoverable afterwards. Fatal only under `runtimeInstaller=mise`; `auto` falls back to aube's own download.",
554        exit_code: Some(88),
555    },
556    CodeMeta {
557        name: ERR_AUBE_RUNTIME_UNSUPPORTED_PLATFORM,
558        category: category::ENGINE_CLI,
559        description: "No official Node.js build exists for this OS/architecture/libc. Set `nodeDownloadMirrors` to a mirror that carries one, or install Node via mise/system.",
560        exit_code: Some(89),
561    },
562    CodeMeta {
563        name: ERR_AUBE_RUNTIME_IO,
564        category: category::ENGINE_CLI,
565        description: "A filesystem operation in the runtime store failed (lock acquisition, staging, or publishing an install). Not a download failure — the message names the failing path.",
566        exit_code: None,
567    },
568    CodeMeta {
569        name: ERR_AUBE_SELF_UPDATE_UNSUPPORTED_PLATFORM,
570        category: category::ENGINE_CLI,
571        description: "`aube self-update` has no published aube release archive for this OS/architecture (e.g. FreeBSD, Intel macOS). Install aube via your system package manager or mise. Distinct from ERR_AUBE_RUNTIME_UNSUPPORTED_PLATFORM, which is about the Node.js download.",
572        exit_code: None,
573    },
574    // Misc / safety
575    CodeMeta {
576        name: ERR_AUBE_INSTALL_CANCELLED,
577        category: category::MISC_SAFETY,
578        description: "An in-process install was cooperatively cancelled by its embedding host. Cancellation is observed at safe install boundaries so an in-flight filesystem phase is not abandoned mid-mutation.",
579        exit_code: None,
580    },
581    CodeMeta {
582        name: ERR_AUBE_UNSAFE_INDEX_KEY,
583        category: category::MISC_SAFETY,
584        description: "A package index key tried to escape its directory (path traversal defense in depth).",
585        exit_code: Some(90),
586    },
587    CodeMeta {
588        name: ERR_AUBE_UNSAFE_SHEBANG_INTERPRETER,
589        category: category::MISC_SAFETY,
590        description: "A `#!` shebang named an unsafe interpreter when generating a shim — substituted with `node` instead. Surfaced as `tracing::error!` but install continues.",
591        exit_code: Some(91),
592    },
593    CodeMeta {
594        name: ERR_AUBE_EMBED_INVALID_PROJECT,
595        category: category::MISC_SAFETY,
596        description: "An in-process embedder was given a project directory that could not be created, inspected, or resolved.",
597        exit_code: None,
598    },
599    CodeMeta {
600        name: ERR_AUBE_EMBED_INSTALL_FAILED,
601        category: category::MISC_SAFETY,
602        description: "An in-process embedder could not initialize its host callback or received an install failure without a more specific stable code.",
603        exit_code: None,
604    },
605    CodeMeta {
606        name: ERR_AUBE_EMBED_INVALID_SETTING,
607        category: category::MISC_SAFETY,
608        description: "An in-process embedder passed a setting default whose name is not a canonical aube setting.",
609        exit_code: None,
610    },
611    CodeMeta {
612        name: ERR_AUBE_EMBED_ALREADY_INITIALIZED,
613        category: category::MISC_SAFETY,
614        description: "An in-process embedder tried to register setting defaults after the process already initialized its embedder profile.",
615        exit_code: None,
616    },
617    CodeMeta {
618        name: ERR_AUBE_FFI_INVALID_ARGUMENT,
619        category: category::MISC_SAFETY,
620        description: "A C ABI call received a null pointer, invalid UTF-8, malformed JSON, or an unsupported option value.",
621        exit_code: None,
622    },
623    CodeMeta {
624        name: ERR_AUBE_FFI_UNKNOWN_HANDLE,
625        category: category::MISC_SAFETY,
626        description: "A C ABI wait or cancellation call referenced an unknown or already-consumed operation handle.",
627        exit_code: None,
628    },
629    CodeMeta {
630        name: ERR_AUBE_FFI_RUNTIME,
631        category: category::MISC_SAFETY,
632        description: "The C ABI could not initialize or use its internal asynchronous runtime.",
633        exit_code: None,
634    },
635    CodeMeta {
636        name: ERR_AUBE_FFI_PANIC,
637        category: category::MISC_SAFETY,
638        description: "A panic was caught at the C ABI boundary before it could cross into the host process.",
639        exit_code: None,
640    },
641    CodeMeta {
642        name: ERR_AUBE_UNSAFE_PACKAGE_NAME,
643        category: category::MISC_SAFETY,
644        description: "A package/dependency alias would escape its `node_modules` slot if linked.",
645        exit_code: Some(92),
646    },
647    CodeMeta {
648        name: ERR_AUBE_PATCHES_TRACKING_WRITE,
649        category: category::MISC_SAFETY,
650        description: "Couldn't write `.aube-applied-patches.json` after applying patches. Non-fatal; next install may miss stale patched entries.",
651        exit_code: None,
652    },
653];