// Error types that more than one layer of quak needs to recognise. // // They live here rather than beside the code that throws them so that the // retry classifier can identify them without importing the HTTP client or the // download layer — both of which import the classifier. `ApiError` is // re-exported from `src/api/client.ts`, which is where callers have always // imported it from and where it still belongs conceptually. export class ApiError extends Error { readonly status: number; readonly code?: string; readonly requestID?: string; readonly body?: unknown; constructor( message: string, status: number, opts?: { code?: string; requestID?: string; body?: unknown }, ) { super(message); this.name = "ApiError"; this.status = status; this.code = opts?.code; this.requestID = opts?.requestID; this.body = opts?.body; } } // A response body that ended before the secretstream did. // // This is a type rather than a message prefix because it is a decision, not a // diagnostic: the retry policy asks "was this a short transfer?" and acts on // the answer. Matching on the wording of an error message would make the next // person to reword a diagnostic silently turn every truncated download into a // permanent failure, and the failure would look like a corrupt file rather // than like a bug. // // `cause` carries the underlying authentication failure on the one path where // there is one — a body that stopped part-way through a chunk, which Poly1305 // cannot distinguish from corruption. export class TruncatedStreamError extends Error { constructor(message: string, opts?: ErrorOptions) { super(message, opts); this.name = "TruncatedStreamError"; } }