1use std::path::PathBuf;
2
3use crate::lock::LockError;
4use crate::validate::ValidationError;
5use crate::walk::WalkerError;
6
7#[derive(Debug, thiserror::Error)]
9#[non_exhaustive]
10pub enum Error {
11 #[error("failed to read {path}", path = path.display())]
14 Read {
15 path: PathBuf,
16 #[source]
17 source: std::io::Error,
18 },
19 #[error("failed to write {path}", path = path.display())]
21 Write {
22 path: PathBuf,
23 #[source]
24 source: std::io::Error,
25 },
26 #[error(transparent)]
28 Walker(#[from] WalkerError),
29 #[error(transparent)]
32 Lock(#[from] LockError),
33 #[error("input '{0}' already exists in the flake")]
36 DuplicateInput(String),
37 #[error("input '{0}' not found in the flake")]
39 InputNotFound(String),
40 #[error(
46 "`add-follow` accepts only depth-1 paths of the form `parent.child`; got '{path}' ({segments} segments)"
47 )]
48 AddFollowDepthLimit { path: String, segments: usize },
49 #[error("validation failed in flake.nix ({} issue(s))", .0.len())]
51 Validation(Vec<ValidationError>),
52}
53
54impl Error {
55 pub fn hint(&self) -> Option<String> {
61 match self {
62 Self::DuplicateInput(id) => Some(format!(
63 "to replace it, run `flake-edit remove {id}` then `flake-edit add {id} <flakeref>`; \
64 or add it under a different id with `flake-edit add [ID] <flakeref>`"
65 )),
66 Self::InputNotFound(id) => Some(format!(
67 "to add it, run `flake-edit add {id} <flakeref>`; \
68 see declared inputs with `flake-edit list`"
69 )),
70 Self::AddFollowDepthLimit { .. } => Some(
71 "use `flake-edit follow` for deeper paths (depth bounded by `follow.max_depth` in your config, if set)"
72 .into(),
73 ),
74 _ => None,
75 }
76 }
77
78 pub fn bullets(&self) -> Option<Vec<String>> {
81 match self {
82 Self::Validation(errors) => Some(errors.iter().map(|e| e.to_string()).collect()),
83 _ => None,
84 }
85 }
86}