Skip to main content

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    /// Static component asset graph failure with a structured diagnostic.
56    #[error("{0}")]
57    ComponentAssets(Box<webui_parser::Diagnostic>),
58
59    /// Bundler-neutral state projection manifest failure: malformed schema,
60    /// stale/missing input or output file, build-ID mismatch, conflicting or
61    /// duplicate fragment ownership, missing scripted-component coverage, or
62    /// an incompatible plugin. Carries a structured, color-free [`Diagnostic`]
63    /// with a stable `PROJ-*` code (see `webui::projection::codes`).
64    ///
65    /// The diagnostic is boxed so this cold error path does not enlarge
66    /// `Result<_, WebUIError>` on the common success path.
67    #[error("{0}")]
68    Projection(Box<webui_parser::Diagnostic>),
69}
70
71impl WebUIError {
72    /// The full, single-line message including the source chain, e.g.
73    /// `Failed to parse index.html: Directive error: Invalid for each: x`.
74    ///
75    /// Each error layer's [`std::fmt::Display`] describes only its own level
76    /// (the `#[source]` chain carries the rest), so the CLI and dev server can
77    /// use anyhow's `{:#}` formatting without repetition. Hosts that surface a
78    /// flat string instead of walking the chain — Node, FFI — use this helper
79    /// to get the same complete message.
80    #[must_use]
81    pub fn chain_message(&self) -> String {
82        let mut message = self.to_string();
83        let mut source = std::error::Error::source(self);
84        while let Some(err) = source {
85            message.push_str(": ");
86            message.push_str(&err.to_string());
87            source = err.source();
88        }
89        message
90    }
91}