afterburner_core/error.rs
1// SPDX-License-Identifier: BUSL-1.1
2// Copyright (c) 2026 vertexclique
3// Licensed under the Business Source License 1.1.
4// Change Date: 4 years after this version's release. Change License: Apache-2.0.
5
6//! Errors produced by any `Combustor` implementation or the `BurnCache`.
7
8use thiserror::Error;
9
10/// Every failure mode Afterburner exposes to callers. Keep the set closed:
11/// callers match on it exhaustively.
12#[derive(Debug, Error)]
13pub enum AfterburnerError {
14 /// JS source failed to compile (syntax error, unsupported construct, etc.).
15 #[error("compile failed: {0}")]
16 CompileFailed(String),
17
18 /// `thrust` was invoked with a `ScriptId` the engine doesn't know about.
19 /// Usually means the script was `extinguish`ed or never `ignite`d.
20 #[error("script not found (hash mismatch or extinguished)")]
21 ScriptNotFound,
22
23 /// The script consumed all fuel allotted by `FuelGauge::fuel`.
24 #[error("fuel exhausted")]
25 FuelExhausted,
26
27 /// The script tried to allocate past `FuelGauge::memory_bytes`.
28 #[error("memory limit exceeded")]
29 MemoryLimit,
30
31 /// Wall-clock `FuelGauge::timeout_ms` elapsed before the script finished.
32 #[error("execution timed out")]
33 Timeout,
34
35 /// The WASM runtime trapped for any reason not caught above (division by
36 /// zero, unreachable, integer overflow, etc.).
37 #[error("wasm trap: {0}")]
38 WasmTrap(String),
39
40 /// JSON could not be produced or consumed at the host boundary.
41 #[error("serialization error: {0}")]
42 Serialize(#[from] serde_json::Error),
43
44 /// The script's result exceeded the per-call output ceiling
45 /// (`FuelGauge::output_bytes`, default 64 MiB). Applies uniformly
46 /// to the JSON result capture, raw result bytes, and script-mode
47 /// stdout. Surfaces as a typed error rather than an opaque
48 /// guest-side I/O trap or a JSON parse failure on truncated bytes.
49 #[error("script output exceeded {limit} byte ceiling (raise FuelGauge::output_bytes)")]
50 OutputTooLarge { limit: usize },
51
52 /// The module returned raw bytes (`Uint8Array` / `ArrayBuffer`)
53 /// through a `Value`-shaped API (`run` / `run_raw`). Use the
54 /// `OutputValue`-returning variants (`run_out` / `run_raw_out`)
55 /// to receive raw results.
56 #[error(
57 "script returned {len} raw bytes; use run_out / run_raw_out (OutputValue) to receive them"
58 )]
59 UnexpectedRawOutput { len: usize },
60
61 /// A host function returned an error to the script.
62 #[error("host error: {0}")]
63 Host(String),
64
65 /// The script requested a capability the active `Manifold` does not
66 /// grant (e.g. `fs.readFileSync` with `FsAccess::None`, or an FS
67 /// path outside the allowed roots). The inner string names the
68 /// denied operation - useful for audit logs and error messages.
69 #[error("permission denied: {0}")]
70 PermissionDenied(String),
71
72 /// The admission layer rejected this thrust because the associated
73 /// tenant's token bucket is empty. Retry after `retry_after_ms`.
74 ///
75 /// `tenant` is the raw `u32` from `TenantId` (or `None` for the
76 /// unrestricted path). Callers can wrap back into `TenantId` if
77 /// they need the newtype.
78 #[error("rate limited (tenant={tenant:?}, retry after {retry_after_ms}ms)")]
79 RateLimited {
80 tenant: Option<u32>,
81 retry_after_ms: u64,
82 },
83
84 /// The thrust engine refused the job because its global in-flight
85 /// cap is reached (pooling-allocator slot exhaustion). This is a
86 /// backpressure signal: slow down or provision more workers.
87 #[error("engine overloaded (in-flight cap reached)")]
88 Overloaded,
89
90 /// The script called `process.exit(n)` inside daemon mode. The CLI
91 /// propagates the exit code to `std::process::exit`; library callers
92 /// can inspect the code and decide what to do.
93 #[error("process.exit({0})")]
94 ProcessExit(i32),
95
96 /// Generic engine-internal failure that doesn't fit a specific variant.
97 /// Use sparingly - prefer adding a typed variant.
98 #[error("engine error: {0}")]
99 Engine(String),
100}
101
102/// Convenience alias used across the workspace.
103pub type Result<T> = core::result::Result<T, AfterburnerError>;