webui/error.rs
1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT license.
3
4//! Error types for the WebUI library.
5
6use thiserror::Error;
7
8/// Errors that can occur during WebUI build, render, or inspection operations.
9#[derive(Debug, Error)]
10pub enum WebUIError {
11 /// I/O error (file read/write failures).
12 #[error("I/O error: {context}")]
13 Io {
14 /// What operation failed.
15 context: String,
16 /// The underlying I/O error.
17 #[source]
18 source: std::io::Error,
19 },
20
21 /// Component registration failure.
22 #[error("Component registration error: {0}")]
23 ComponentRegistration(String),
24
25 /// Component discovery failure (npm packages or local paths).
26 #[error("Component discovery error: {0}")]
27 ComponentDiscovery(String),
28
29 /// HTML/CSS parsing failure with context about which file failed.
30 #[error("{context}")]
31 Parse {
32 /// What was being parsed.
33 context: String,
34 /// The underlying parse error.
35 #[source]
36 source: webui_parser::ParserError,
37 },
38
39 /// Protocol serialization or deserialization failure.
40 #[error("protocol error")]
41 Protocol(#[from] webui_protocol::ProtocolError),
42
43 /// JSON serialization failure.
44 #[error("Serialization error: {0}")]
45 Serialization(String),
46
47 /// Handler rendering error.
48 #[error("rendering error")]
49 Rendering(#[from] webui_handler::HandlerError),
50
51 /// Invalid build-option configuration.
52 #[error("Invalid build options: {0}")]
53 InvalidBuildOptions(String),
54
55 /// Bundler-neutral state projection manifest failure: malformed schema,
56 /// stale/missing input or output file, build-ID mismatch, conflicting or
57 /// duplicate fragment ownership, missing scripted-component coverage, or
58 /// an incompatible plugin. Carries a structured, color-free [`Diagnostic`]
59 /// with a stable `PROJ-*` code (see `webui::projection::codes`).
60 ///
61 /// The diagnostic is boxed so this cold error path does not enlarge
62 /// `Result<_, WebUIError>` on the common success path.
63 #[error("{0}")]
64 Projection(Box<webui_parser::Diagnostic>),
65}
66
67impl WebUIError {
68 /// The full, single-line message including the source chain, e.g.
69 /// `Failed to parse index.html: Directive error: Invalid for each: x`.
70 ///
71 /// Each error layer's [`std::fmt::Display`] describes only its own level
72 /// (the `#[source]` chain carries the rest), so the CLI and dev server can
73 /// use anyhow's `{:#}` formatting without repetition. Hosts that surface a
74 /// flat string instead of walking the chain — Node, FFI — use this helper
75 /// to get the same complete message.
76 #[must_use]
77 pub fn chain_message(&self) -> String {
78 let mut message = self.to_string();
79 let mut source = std::error::Error::source(self);
80 while let Some(err) = source {
81 message.push_str(": ");
82 message.push_str(&err.to_string());
83 source = err.source();
84 }
85 message
86 }
87}