Skip to main content

newt_data/
error.rs

1//! Error type for the Phase 21 `newt-data` engine.
2//!
3//! See [`docs/design/centaur-data-scientist.md`](../../../docs/design/centaur-data-scientist.md):
4//! the engine is headless and surfaces every failure as a typed [`DataError`]
5//! so the later MCP adapter (step 21.2) and PyO3 submodule (step 21.6) can map
6//! each variant to an honest, machine-readable error without string-sniffing.
7
8use thiserror::Error;
9
10/// Everything that can go wrong inside the `newt-data` SQLite engine.
11///
12/// The three `#[from]` variants wrap the upstream errors verbatim so the
13/// underlying cause is never lost; the remaining variants are the engine's own
14/// invariant violations (Phase 21 — identifier safety, table existence, and
15/// the empty-CSV guard described in
16/// [`docs/design/centaur-data-scientist.md`](../../../docs/design/centaur-data-scientist.md)).
17#[derive(Debug, Error)]
18pub enum DataError {
19    /// A SQLite operation failed (open, pragma, prepare, step, bind, …).
20    #[error("sqlite error: {0}")]
21    Sqlite(#[from] rusqlite::Error),
22
23    /// The CSV reader failed to parse the input (malformed record, unequal
24    /// field counts under `flexible = false`, encoding, …).
25    #[error("csv error: {0}")]
26    Csv(#[from] csv::Error),
27
28    /// A filesystem operation failed (creating the parent dir, opening the
29    /// CSV path, …).
30    #[error("io error: {0}")]
31    Io(#[from] std::io::Error),
32
33    /// A table identifier supplied to [`ingest_csv`](crate::DataStore::ingest_csv)
34    /// is not a safe SQLite identifier: empty, or containing a NUL byte or a
35    /// double-quote. Defense in depth on top of the always-on
36    /// double-quote quoting (Phase 21 — identifier safety is a review focus).
37    #[error("invalid SQL identifier `{0}`: table names may not be empty or contain NUL / double-quote characters")]
38    InvalidIdentifier(String),
39
40    /// A table referenced by [`summarize`](crate::DataStore::summarize) does
41    /// not exist in the database.
42    #[error("no such table: `{0}`")]
43    NoSuchTable(String),
44
45    /// The CSV had no header row, so no columns could be created.
46    #[error("empty csv: no header row")]
47    EmptyCsv,
48
49    /// An `.ipynb` notebook (Phase 21.4 — [`crate::notebook`]) could not be
50    /// read, parsed, or validated: the file is not valid JSON, its top-level
51    /// value is not an object, its `nbformat` is not `4`, or it is otherwise not
52    /// a well-formed nbformat-4 document. The message names the offending file
53    /// and the specific reason so the MCP adapter surfaces an honest, in-band
54    /// tool error the model can read (never a panic). See
55    /// [`docs/design/centaur-data-scientist.md`](../../../docs/design/centaur-data-scientist.md)
56    /// §4.1, the notebook-artifact bullet.
57    #[error("invalid notebook: {0}")]
58    InvalidNotebook(String),
59}
60
61/// Crate-wide result alias over [`DataError`].
62pub type Result<T> = std::result::Result<T, DataError>;