Skip to main content

helm_schema/
error.rs

1use std::path::PathBuf;
2
3/// Errors produced while loading charts, analyzing templates, and emitting schemas.
4#[derive(Debug, thiserror::Error)]
5pub enum CliError {
6    /// Virtual-filesystem operation failed.
7    #[error("vfs error: {0}")]
8    Vfs(#[from] vfs::VfsError),
9
10    /// Operating-system I/O operation failed.
11    #[error("io error: {0}")]
12    Io(#[from] std::io::Error),
13
14    /// YAML input could not be decoded.
15    #[error("yaml error: {0}")]
16    Yaml(#[from] serde_yaml::Error),
17
18    /// Values declarations use keys whose spelling Helm normalizes ambiguously.
19    #[error(
20        "unquoted YAML 1.1 Boolean-alias keys are not supported in chart declarations:\n{details}"
21    )]
22    YamlBooleanAliasKeys {
23        /// Deterministically ordered file locations and source spellings.
24        details: String,
25    },
26
27    /// A values declaration could not be structurally inspected for key style.
28    #[error("failed to inspect YAML Boolean-alias keys in {path}: {message}")]
29    YamlBooleanAliasScan {
30        /// Values declaration being inspected.
31        path: String,
32        /// YAML parser failure.
33        message: String,
34    },
35
36    /// A chart declares the same dependency name more than once.
37    #[error(
38        "duplicate dependency names are not supported in {path}:\n{details}\ndependency names must be unique because Helm's installed-chart association is nondeterministic"
39    )]
40    DuplicateDependencyNames {
41        /// Manifest containing the duplicate declarations.
42        path: String,
43        /// Deterministically ordered names and declaration counts.
44        details: String,
45    },
46
47    /// JSON input or output could not be decoded or encoded.
48    #[error("json error: {0}")]
49    Json(#[from] serde_json::Error),
50
51    /// A caller override is not a JSON Schema document root.
52    #[error("override schema root in {path} must be an object or boolean, found {kind}")]
53    InvalidOverrideRoot {
54        /// Override file carrying the invalid root.
55        path: PathBuf,
56        /// JSON kind found at the document root.
57        kind: &'static str,
58    },
59
60    /// A final output document is not a JSON Schema root.
61    #[error("final schema root must be an object or boolean, found {kind}")]
62    InvalidFinalSchemaRoot {
63        /// JSON kind found at the document root.
64        kind: &'static str,
65    },
66
67    /// Helm template source could not be parsed.
68    #[error("template parse error: {0}")]
69    TemplateParse(#[from] helm_schema_ast::ParseError),
70
71    /// Chart discovery found no analyzable charts.
72    #[error("no charts discovered")]
73    NoChartsDiscovered,
74
75    /// A discovered subchart path has no usable chart name.
76    #[error("subchart name missing for {path}")]
77    SubchartNameMissing {
78        /// Path of the unnamed subchart.
79        path: String,
80    },
81
82    /// An archive does not contain a chart manifest.
83    #[error("no Chart.yaml found in archive {archive}")]
84    NoChartYamlInArchive {
85        /// Path or identifier of the archive.
86        archive: String,
87    },
88
89    /// The output directory could not be created.
90    #[error("failed to create output directory {path}")]
91    CreateOutputDir {
92        /// Directory creation target.
93        path: PathBuf,
94        /// Underlying filesystem failure.
95        #[source]
96        source: std::io::Error,
97    },
98
99    /// A generated schema could not be written.
100    #[error("failed to write output {path}")]
101    WriteOutput {
102        /// Output file that could not be written.
103        path: PathBuf,
104        /// Underlying filesystem failure.
105        #[source]
106        source: std::io::Error,
107    },
108
109    /// Wraps any failure surfaced by the `jsonschema` / `referencing`
110    /// full-inlining pass: file-not-found, JSON parse error, malformed
111    /// URI, pointer-to-nowhere, missing anchor, etc. The wrapped variant
112    /// carries the structured cause so callers can pattern-match on the
113    /// underlying problem (e.g. `Unretrievable { uri, source }` vs
114    /// `PointerToNowhere { pointer }`) rather than parsing a string.
115    #[error("$ref resolution failed: {0}")]
116    Referencing(#[from] jsonschema::ReferencingError),
117
118    /// A self-contained schema could not be produced from external references.
119    #[error("$ref bundling failed: {0}")]
120    RefBundling(String),
121
122    /// A local filesystem path cannot be represented as a file URI.
123    #[error("filesystem path cannot be represented as a file URI: {path}")]
124    InvalidFileUriPath {
125        /// Filesystem path that could not be encoded.
126        path: PathBuf,
127    },
128
129    /// A file URI cannot be represented as a local filesystem path.
130    #[error("file URI cannot be represented as a local filesystem path: {uri}")]
131    InvalidFileUri {
132        /// File URI that could not be decoded.
133        uri: String,
134    },
135
136    /// One loaded document exceeded the configured byte budget.
137    #[error("load budget exceeded for {subject} (limit {limit_bytes} bytes)")]
138    LoadBudgetExceeded {
139        /// Document or archive member being loaded.
140        subject: String,
141        /// Maximum permitted byte count.
142        limit_bytes: usize,
143    },
144
145    /// An archive or directory exceeded the configured entry budget.
146    #[error("load budget exceeded for {subject} (limit {limit_entries} entries)")]
147    LoadEntryBudgetExceeded {
148        /// Archive or directory being enumerated.
149        subject: String,
150        /// Maximum permitted entry count.
151        limit_entries: usize,
152    },
153
154    /// An archive member would escape its extraction root.
155    #[error("unsafe archive entry path {entry_path} in {archive}")]
156    UnsafeArchiveEntryPath {
157        /// Archive containing the unsafe member.
158        archive: String,
159        /// Untrusted member path rejected by validation.
160        entry_path: String,
161    },
162
163    /// Mutually-exclusive CLI flags or otherwise-invalid combination
164    /// detected after `clap` parsing succeeded.
165    #[error("invalid CLI options: {0}")]
166    CliValidation(String),
167
168    /// An emission selection resolves to a contradictory knob matrix.
169    #[error("invalid emission policy: {0}")]
170    InvalidEmissionPolicy(#[from] helm_schema_gen::InvalidEmissionPolicy),
171
172    /// An explicit config path could not be read.
173    #[error("failed to read config {path}: {source}")]
174    ConfigRead {
175        /// Config file path.
176        path: PathBuf,
177        /// Underlying filesystem failure.
178        #[source]
179        source: std::io::Error,
180    },
181
182    /// A config document is malformed or contains unknown fields.
183    #[error("invalid config {path}: {source}")]
184    InvalidConfig {
185        /// Config file path or packaged-chart member label.
186        path: String,
187        /// YAML decoding failure.
188        #[source]
189        source: serde_yaml::Error,
190    },
191
192    /// A config document uses a version this binary cannot honor exactly.
193    #[error(
194        "unsupported config version {found} in {path}; supported range is {supported_min}..={supported_max}; update the config or the helm-schema binary"
195    )]
196    UnsupportedConfigVersion {
197        /// Config file path.
198        path: PathBuf,
199        /// Version requested by the config.
200        found: u64,
201        /// Oldest config version honored by this binary.
202        supported_min: u64,
203        /// Newest config version honored by this binary.
204        supported_max: u64,
205    },
206}
207
208/// Result returned by the schema engine's public operations.
209pub type EngineResult<T> = std::result::Result<T, CliError>;