forge_dictate/error.rs
1//! Error taxonomy for the crate.
2
3use std::path::PathBuf;
4
5/// Everything this crate can fail with.
6#[derive(Debug, thiserror::Error)]
7pub enum Error {
8 /// No models directory was configured and the platform cache
9 /// directory could not be resolved.
10 #[error("no cache directory available; set Config::models_dir explicitly")]
11 NoCacheDir,
12
13 /// A filesystem operation on `path` failed. A transfer that dies
14 /// mid-body lands here too rather than in [`Error::Http`]: it
15 /// surfaces while reading the response, and `path` labels the
16 /// partial being written rather than naming what actually failed.
17 #[error("{}: {source}", path.display())]
18 Io {
19 path: PathBuf,
20 #[source]
21 source: std::io::Error,
22 },
23
24 /// The request failed before any body arrived - connection, TLS, or
25 /// a refused handshake.
26 #[error("could not fetch {url}: {source}")]
27 Http {
28 url: String,
29 #[source]
30 source: reqwest::Error,
31 },
32
33 /// The server answered, but not with the file.
34 #[error("{url} returned HTTP {status}")]
35 HttpStatus { url: String, status: u16 },
36
37 /// A file on disk is not the length the spec records. The usual
38 /// cause is an interrupted download that was never resumed.
39 #[error("{} is {actual} bytes, expected {expected}", path.display())]
40 SizeMismatch { path: PathBuf, expected: u64, actual: u64 },
41
42 /// Work was stopped on request rather than by a fault: a progress
43 /// callback returning `Break` during a fetch, or an abandoned
44 /// [`crate::Ticket`] aborting an inference.
45 ///
46 /// Whatever already finished is kept - a model that reached
47 /// [`crate::Progress::Ready`] is installed - and any partial transfer
48 /// is left where it is, so a later call resumes rather than starting
49 /// over.
50 #[error("cancelled on request")]
51 Cancelled,
52
53 /// The source declares a rate the models cannot read. Rejected
54 /// rather than resampled: a silent resample yields plausible text
55 /// from the wrong signal, and nothing downstream can detect that.
56 #[error("audio is {actual} Hz, expected {expected} Hz; resample before transcribing")]
57 SampleRate { expected: u32, actual: u32 },
58
59 /// The source declares more than one channel. Interleaved stereo
60 /// read as mono is a plausible doubled-rate signal, not an error, so
61 /// it is refused at the boundary.
62 #[error("audio has {actual} channels, expected mono; downmix before transcribing")]
63 Channels { actual: u16 },
64
65 /// Opening or running the input stream failed.
66 #[error("microphone capture failed: {message}")]
67 Capture { message: String },
68
69 /// The transcription worker could not be started.
70 #[error("could not start the transcription worker: {message}")]
71 WorkerSpawn { message: String },
72
73 /// The weights could not be loaded.
74 #[error("could not load the model at {}: {message}", path.display())]
75 ModelLoad { path: PathBuf, message: String },
76
77 /// Recognition itself failed.
78 #[error("recognition failed: {message}")]
79 Recognition { message: String },
80
81 /// The worker is gone, so nothing can be transcribed and no queued
82 /// result will ever arrive.
83 #[error("the transcription worker has stopped")]
84 EngineStopped,
85
86 /// A partial does not match its spec and could not be removed, so
87 /// every later call fails identically until someone clears it. The
88 /// usual cause is a models directory that is not writable.
89 #[error("{} does not match its spec and could not be removed ({source}); remove it to unblock", path.display())]
90 StalePartial {
91 path: PathBuf,
92 #[source]
93 source: std::io::Error,
94 },
95
96 /// A file on disk is the right length but the wrong bytes.
97 #[error("{} hashes to {actual}, expected {expected}", path.display())]
98 HashMismatch { path: PathBuf, expected: String, actual: String },
99
100 /// A catalogue document is not an entry this build reads.
101 #[error("catalogue: {message}")]
102 Catalogue { message: String },
103
104 /// A bench's corpus could not be read: a wav that is not the shape
105 /// this crate reads, or a fixture set that disagrees with itself.
106 #[error("bench: {message}")]
107 Bench { message: String },
108}