1use ::routing::error::{ComponentInstanceError, RoutingError};
6use ::routing::policy::PolicyError;
7use ::routing::resolving::ResolverError;
8use anyhow::Error;
9use clonable_error::ClonableError;
10use cm_config::CompatibilityCheckError;
11use cm_rust::UseDecl;
12use cm_types::{Name, Url};
13use component_id_index::InstanceId;
14use fidl_fuchsia_component as fcomponent;
15use fidl_fuchsia_sys2 as fsys;
16use fuchsia_fs::directory::WatcherCreateError;
17use moniker::{ChildName, ExtendedMoniker, Moniker, MonikerError};
18use router_error::{Explain, RouterError};
19use sandbox::ConversionError;
20use serve_processargs::BuildNamespaceError;
21use std::sync::Arc;
22use thiserror::Error;
23
24#[derive(Debug, Error, Clone)]
26pub enum ModelError {
27 #[error("bad path")]
28 BadPath,
29 #[error(transparent)]
30 MonikerError {
31 #[from]
32 err: MonikerError,
33 },
34 #[error("expected a component instance moniker")]
35 UnexpectedComponentManagerMoniker,
36 #[error(transparent)]
37 RoutingError {
38 #[from]
39 err: RoutingError,
40 },
41 #[error(
42 "opening path `{path}`, in storage directory for `{moniker}` backed by `{source_moniker}`: {err}"
43 )]
44 OpenStorageFailed {
45 source_moniker: ExtendedMoniker,
46 moniker: Moniker,
47 path: String,
48 #[source]
49 err: zx::Status,
50 },
51 #[error(transparent)]
52 StorageError {
53 #[from]
54 err: StorageError,
55 },
56 #[error(transparent)]
57 ComponentInstanceError {
58 #[from]
59 err: ComponentInstanceError,
60 },
61 #[error("service dir VFS for component {moniker}:\n\t{err}")]
62 ServiceDirError {
63 moniker: Moniker,
64
65 #[source]
66 err: VfsError,
67 },
68 #[error("opening directory `{relative_path}` for component `{moniker}` failed")]
69 OpenDirectoryError { moniker: Moniker, relative_path: String },
70 #[error("events: {err}")]
71 EventsError {
72 #[from]
73 err: EventsError,
74 },
75 #[error(transparent)]
76 PolicyError {
77 #[from]
78 err: PolicyError,
79 },
80 #[error("component id index: {err}")]
81 ComponentIdIndexError {
82 #[from]
83 err: component_id_index::IndexError,
84 },
85 #[error(transparent)]
86 ActionError {
87 #[from]
88 err: ActionError,
89 },
90 #[error("resolve: {err}")]
91 ResolveActionError {
92 #[from]
93 err: ResolveActionError,
94 },
95 #[error("start: {err}")]
96 StartActionError {
97 #[from]
98 err: StartActionError,
99 },
100 #[error("open outgoing dir: {err}")]
101 OpenOutgoingDirError {
102 #[from]
103 err: OpenOutgoingDirError,
104 },
105 #[error("router: {err}")]
106 RouterError {
107 #[from]
108 err: RouterError,
109 },
110 #[error("capability provider: {err}")]
111 CapabilityProviderError {
112 #[from]
113 err: CapabilityProviderError,
114 },
115 #[error("open: {err}")]
116 OpenError {
117 #[from]
118 err: OpenError,
119 },
120}
121
122impl ModelError {
123 pub fn instance_not_found(moniker: Moniker) -> ModelError {
124 ModelError::from(ComponentInstanceError::instance_not_found(moniker))
125 }
126
127 pub fn open_directory_error(moniker: Moniker, relative_path: impl Into<String>) -> ModelError {
128 ModelError::OpenDirectoryError { moniker, relative_path: relative_path.into() }
129 }
130}
131
132impl ModelError {
133 fn as_zx_status(&self) -> zx::Status {
134 match self {
135 ModelError::RoutingError { err } => err.as_zx_status(),
136 ModelError::PolicyError { err } => err.as_zx_status(),
137 ModelError::StartActionError { err } => err.as_zx_status(),
138 ModelError::ComponentInstanceError { err } => err.as_zx_status(),
139 ModelError::OpenOutgoingDirError { err } => err.as_zx_status(),
140 ModelError::RouterError { err } => err.as_zx_status(),
141 ModelError::CapabilityProviderError { err } => err.as_zx_status(),
142 _ => zx::Status::INTERNAL,
144 }
145 }
146}
147
148#[derive(Debug, Error, Clone)]
149pub enum StructuredConfigError {
150 #[error("component has a config schema but resolver did not provide values")]
151 ConfigValuesMissing,
152 #[error("failed to resolve component's config:\n\t{_0}")]
153 ConfigResolutionFailed(#[source] config_encoder::ResolutionError),
154 #[error("couldn't create vmo: {_0}")]
155 VmoCreateFailed(#[source] zx::Status),
156 #[error("failed to match values for key `{key}`")]
157 ValueMismatch { key: String },
158 #[error("failed to find values for key `{key}`")]
159 KeyNotFound { key: String },
160 #[error("failed to route structured config values:\n\t{_0}")]
161 RoutingError(#[from] router_error::RouterError),
162}
163
164#[derive(Clone, Debug, Error)]
165pub enum VfsError {
166 #[error("failed to add node `{name}`: {status}")]
167 AddNodeError { name: String, status: zx::Status },
168 #[error("failed to remove node `{name}`: {status}")]
169 RemoveNodeError { name: String, status: zx::Status },
170}
171
172#[derive(Debug, Error)]
173pub enum RebootError {
174 #[error("failed to connect to admin protocol in root component's exposed dir:\n\t{0}")]
175 ConnectToAdminFailed(#[source] anyhow::Error),
176 #[error("StateControl Admin FIDL:\n\t{0}")]
177 FidlError(#[from] fidl::Error),
178 #[error("StateControl Admin: {0}")]
179 AdminError(zx::Status),
180 #[error("opening root component's exposed dir: {0}")]
181 OpenRootExposedDirFailed(#[from] OpenExposedDirError),
182}
183
184#[derive(Debug, Error)]
185pub enum OpenExposedDirError {
186 #[error("instance is not resolved")]
187 InstanceNotResolved,
188 #[error("instance was destroyed")]
189 InstanceDestroyed,
190 #[error("open error: {0}")]
191 Open(#[from] zx::Status),
192}
193
194impl Explain for OpenExposedDirError {
195 fn as_zx_status(&self) -> zx::Status {
196 match self {
197 Self::InstanceNotResolved => zx::Status::NOT_FOUND,
198 Self::InstanceDestroyed => zx::Status::NOT_FOUND,
199 Self::Open(status) => *status,
200 }
201 }
202}
203
204impl From<OpenExposedDirError> for fsys::OpenError {
205 fn from(value: OpenExposedDirError) -> Self {
206 match value {
207 OpenExposedDirError::InstanceNotResolved => fsys::OpenError::InstanceNotResolved,
208 OpenExposedDirError::InstanceDestroyed => fsys::OpenError::InstanceDestroyed,
209 OpenExposedDirError::Open(_) => fsys::OpenError::FidlError,
210 }
211 }
212}
213
214#[derive(Clone, Debug, Error)]
215pub enum OpenOutgoingDirError {
216 #[error("instance is not resolved")]
217 InstanceNotResolved,
218 #[error("instance is non-executable")]
219 InstanceNonExecutable,
220 #[error("failed to open: {0}")]
221 Open(#[from] zx::Status),
222 #[error("fidl IPC to protocol in outgoing directory:\n\t{0}")]
223 Fidl(fidl::Error),
224}
225
226impl Explain for OpenOutgoingDirError {
227 fn as_zx_status(&self) -> zx::Status {
228 match self {
229 Self::InstanceNotResolved => zx::Status::NOT_FOUND,
230 Self::InstanceNonExecutable => zx::Status::NOT_FOUND,
231 Self::Open(err) => *err,
232 Self::Fidl(_) => zx::Status::NOT_FOUND,
233 }
234 }
235}
236
237impl From<OpenOutgoingDirError> for fsys::OpenError {
238 fn from(value: OpenOutgoingDirError) -> Self {
239 match value {
240 OpenOutgoingDirError::InstanceNotResolved => fsys::OpenError::InstanceNotResolved,
241 OpenOutgoingDirError::InstanceNonExecutable => fsys::OpenError::NoSuchDir,
242 OpenOutgoingDirError::Open(_) => fsys::OpenError::FidlError,
243 OpenOutgoingDirError::Fidl(_) => fsys::OpenError::FidlError,
244 }
245 }
246}
247
248impl From<OpenOutgoingDirError> for RouterError {
249 fn from(value: OpenOutgoingDirError) -> Self {
250 Self::NotFound(Arc::new(value))
251 }
252}
253
254#[derive(Debug, Error, Clone)]
255pub enum AddDynamicChildError {
256 #[error("component collection not found with name `{name}`")]
257 CollectionNotFound { name: String },
258 #[error(
259 "numbered handles can only be provided when adding components to a single-run collection"
260 )]
261 NumberedHandleNotInSingleRunCollection,
262 #[error("name length is longer than the allowed max of {max_len}")]
263 NameTooLong { max_len: usize },
264 #[error("collection `{collection_name}` does not allow dynamic offers")]
265 DynamicOffersNotAllowed { collection_name: String },
266 #[error(transparent)]
267 ActionError {
268 #[from]
269 err: ActionError,
270 },
271 #[error("invalid dictionary")]
272 InvalidDictionary,
273 #[error(
274 "dictionary entry for capability `{capability_name}` conflicts with existing static route"
275 )]
276 StaticRouteConflict { capability_name: Name },
277 #[error(transparent)]
278 AddChildError {
279 #[from]
280 err: AddChildError,
281 },
282 #[error("cannot set both `dictionary` and `additional_inputs`")]
283 DictionaryAndAdditionalInputsSet,
284}
285
286impl Into<fcomponent::Error> for AddDynamicChildError {
288 fn into(self) -> fcomponent::Error {
289 match self {
290 AddDynamicChildError::CollectionNotFound { .. } => {
291 fcomponent::Error::CollectionNotFound
292 }
293 AddDynamicChildError::NumberedHandleNotInSingleRunCollection => {
294 fcomponent::Error::Unsupported
295 }
296 AddDynamicChildError::AddChildError {
297 err: AddChildError::InstanceAlreadyExists { .. },
298 } => fcomponent::Error::InstanceAlreadyExists,
299 AddDynamicChildError::DynamicOffersNotAllowed { .. } => {
300 fcomponent::Error::InvalidArguments
301 }
302 AddDynamicChildError::ActionError { err } => err.into(),
303 AddDynamicChildError::InvalidDictionary { .. } => fcomponent::Error::InvalidArguments,
304 AddDynamicChildError::StaticRouteConflict { .. } => fcomponent::Error::InvalidArguments,
305 AddDynamicChildError::NameTooLong { .. } => fcomponent::Error::InvalidArguments,
306 AddDynamicChildError::AddChildError {
309 err:
310 AddChildError::DynamicCapabilityError { err: DynamicCapabilityError::Cycle { .. } },
311 } => fcomponent::Error::DependencyCycle,
312 AddDynamicChildError::AddChildError {
313 err: AddChildError::DynamicCapabilityError { .. },
314 } => fcomponent::Error::InvalidArguments,
315 AddDynamicChildError::AddChildError { err: AddChildError::ChildNameInvalid { .. } } => {
316 fcomponent::Error::InvalidArguments
317 }
318 AddDynamicChildError::DictionaryAndAdditionalInputsSet => {
319 fcomponent::Error::InvalidArguments
320 }
321 }
322 }
323}
324
325impl Into<fsys::CreateError> for AddDynamicChildError {
327 fn into(self) -> fsys::CreateError {
328 match self {
329 AddDynamicChildError::CollectionNotFound { .. } => {
330 fsys::CreateError::CollectionNotFound
331 }
332 AddDynamicChildError::AddChildError {
333 err: AddChildError::InstanceAlreadyExists { .. },
334 } => fsys::CreateError::InstanceAlreadyExists,
335
336 AddDynamicChildError::DynamicOffersNotAllowed { .. } => {
337 fsys::CreateError::DynamicOffersForbidden
338 }
339 AddDynamicChildError::ActionError { .. } => fsys::CreateError::Internal,
340 AddDynamicChildError::InvalidDictionary { .. } => fsys::CreateError::Internal,
341 AddDynamicChildError::StaticRouteConflict { .. } => fsys::CreateError::Internal,
342 AddDynamicChildError::NameTooLong { .. } => fsys::CreateError::BadChildDecl,
343 AddDynamicChildError::AddChildError {
344 err: AddChildError::DynamicCapabilityError { .. },
345 } => fsys::CreateError::BadDynamicOffer,
346 AddDynamicChildError::AddChildError { err: AddChildError::ChildNameInvalid { .. } } => {
347 fsys::CreateError::BadMoniker
348 }
349 AddDynamicChildError::NumberedHandleNotInSingleRunCollection => {
350 fsys::CreateError::NumberedHandlesForbidden
351 }
352 AddDynamicChildError::DictionaryAndAdditionalInputsSet => {
353 fsys::CreateError::DictionaryAndAdditionalInputsSet
354 }
355 }
356 }
357}
358
359#[derive(Debug, Error, Clone)]
360pub enum AddChildError {
361 #[error("component instance `{child}` in realm `{moniker}` already exists")]
362 InstanceAlreadyExists { moniker: Moniker, child: ChildName },
363 #[error(transparent)]
364 DynamicCapabilityError {
365 #[from]
366 err: DynamicCapabilityError,
367 },
368 #[error("invalid child name: {err}")]
369 ChildNameInvalid {
370 #[from]
371 err: MonikerError,
372 },
373}
374
375#[derive(Debug, Error, Clone, PartialEq)]
376pub enum DynamicCapabilityError {
377 #[error("a dynamic capability was not valid:\n\t{err}")]
378 Invalid {
379 #[source]
380 err: cm_fidl_validator::error::ErrorList,
381 },
382 #[error("dynamic offers are not allowed for {typename}")]
383 UnsupportedType { typename: &'static str },
384 #[error("dynamic offer would create a cycle:\n\t{err}")]
385 Cycle {
386 #[source]
387 err: cm_fidl_validator::error::ErrorList,
388 },
389 #[error("source for dynamic offer not found:\n\t{:?}", offer)]
390 SourceNotFound { offer: cm_rust::offer::OfferDecl },
391 #[error("unknown offer type in dynamic offers")]
392 UnknownOfferType,
393}
394
395#[derive(Debug, Clone, Error)]
396#[error(transparent)]
397pub struct ActionError {
398 kind: Box<ActionErrorKind>,
399}
400
401impl ActionError {
402 pub fn kind(&self) -> &ActionErrorKind {
403 &self.kind
404 }
405}
406
407impl From<ActionErrorKind> for ActionError {
408 fn from(err: ActionErrorKind) -> Self {
409 ActionError { kind: Box::new(err) }
410 }
411}
412
413macro_rules! impl_from_action_error_kind {
414 ($($ty:ty,)+) => {
415 $(
416 impl From<$ty> for ActionError {
417 fn from(err: $ty) -> Self {
418 ActionError::from(ActionErrorKind::from(err))
419 }
420 }
421 )+
422 }
423}
424
425impl_from_action_error_kind! {
426 DiscoverActionError,
427 ResolveActionError,
428 UnresolveActionError,
429 StartActionError,
430 StopActionError,
431 DestroyActionError,
432 ShutdownActionError,
433}
434
435#[derive(Debug, Clone, Error)]
436pub enum ActionErrorKind {
437 #[error("discover: {err}")]
438 DiscoverError {
439 #[from]
440 err: DiscoverActionError,
441 },
442
443 #[error("resolve: {err}")]
444 ResolveError {
445 #[from]
446 err: ResolveActionError,
447 },
448
449 #[error("unresolve: {err}")]
450 UnresolveError {
451 #[from]
452 err: UnresolveActionError,
453 },
454
455 #[error("start: {err}")]
456 StartError {
457 #[from]
458 err: StartActionError,
459 },
460
461 #[error("stop: {err}")]
462 StopError {
463 #[from]
464 err: StopActionError,
465 },
466
467 #[error("destroy: {err}")]
468 DestroyError {
469 #[from]
470 err: DestroyActionError,
471 },
472
473 #[error("shutdown: {err}")]
474 ShutdownError {
475 #[from]
476 err: ShutdownActionError,
477 },
478}
479
480impl Explain for ActionError {
481 fn as_zx_status(&self) -> zx::Status {
482 match &*self.kind {
483 ActionErrorKind::DiscoverError { .. } => zx::Status::INTERNAL,
484 ActionErrorKind::ResolveError { err } => err.as_zx_status(),
485 ActionErrorKind::UnresolveError { .. } => zx::Status::INTERNAL,
486 ActionErrorKind::StartError { err } => err.as_zx_status(),
487 ActionErrorKind::StopError { .. } => zx::Status::INTERNAL,
488 ActionErrorKind::DestroyError { .. } => zx::Status::INTERNAL,
489 ActionErrorKind::ShutdownError { .. } => zx::Status::INTERNAL,
490 }
491 }
492}
493
494impl From<ActionError> for fcomponent::Error {
495 fn from(err: ActionError) -> Self {
496 match *err.kind {
497 ActionErrorKind::DiscoverError { .. } => fcomponent::Error::Internal,
498 ActionErrorKind::ResolveError { .. } => fcomponent::Error::Internal,
499 ActionErrorKind::UnresolveError { .. } => fcomponent::Error::Internal,
500 ActionErrorKind::StartError { err } => err.into(),
501 ActionErrorKind::StopError { err } => err.into(),
502 ActionErrorKind::DestroyError { err } => err.into(),
503 ActionErrorKind::ShutdownError { .. } => fcomponent::Error::Internal,
504 }
505 }
506}
507
508impl From<ActionError> for fsys::ResolveError {
509 fn from(err: ActionError) -> Self {
510 match *err.kind {
511 ActionErrorKind::ResolveError { err } => err.into(),
512 _ => fsys::ResolveError::Internal,
513 }
514 }
515}
516
517impl From<ActionError> for fsys::UnresolveError {
518 fn from(err: ActionError) -> Self {
519 match *err.kind {
520 ActionErrorKind::UnresolveError { err } => err.into(),
521 _ => fsys::UnresolveError::Internal,
522 }
523 }
524}
525
526impl From<ActionError> for fsys::StartError {
527 fn from(err: ActionError) -> Self {
528 match *err.kind {
529 ActionErrorKind::StartError { err } => err.into(),
530 _ => fsys::StartError::Internal,
531 }
532 }
533}
534
535impl From<ActionError> for fsys::StopError {
536 fn from(err: ActionError) -> Self {
537 match *err.kind {
538 ActionErrorKind::StopError { err } => err.into(),
539 _ => fsys::StopError::Internal,
540 }
541 }
542}
543
544impl From<ActionError> for fsys::DestroyError {
545 fn from(err: ActionError) -> Self {
546 match *err.kind {
547 ActionErrorKind::DestroyError { err } => err.into(),
548 _ => fsys::DestroyError::Internal,
549 }
550 }
551}
552
553#[derive(Debug, Clone, Error)]
554pub enum DiscoverActionError {
555 #[error("`{moniker}` was destroyed")]
556 InstanceDestroyed { moniker: Moniker },
557}
558
559#[derive(Debug, Clone, Error)]
560pub enum ResolveActionError {
561 #[error("discover during resolve: {err}")]
562 DiscoverActionError {
563 #[from]
564 err: DiscoverActionError,
565 },
566 #[error("`{moniker}` was shut down")]
567 InstanceShutDown { moniker: Moniker },
568 #[error("`{moniker}` was destroyed")]
569 InstanceDestroyed { moniker: Moniker },
570 #[error("could not parse component address for `{url}` at `{moniker}`:\n\t{err}")]
571 ComponentAddressParseError {
572 url: Url,
573 moniker: Moniker,
574 #[source]
575 err: ResolverError,
576 },
577 #[error("resolve failed for `{url}`:\n\t{err}")]
578 ResolverError {
579 url: Url,
580 #[source]
581 err: ResolverError,
582 },
583 #[error("expose dir for `{moniker}`:\n\t{err}")]
584 ExposeDirError {
586 moniker: Moniker,
587
588 #[source]
589 err: VfsError,
590 },
591 #[error("adding static child `{child_name}`:\n\t{err}")]
592 AddStaticChildError {
593 child_name: String,
594 #[source]
595 err: AddChildError,
596 },
597 #[error("structured config: {err}")]
598 StructuredConfigError {
599 #[from]
600 err: StructuredConfigError,
601 },
602 #[error("creating package dir proxy: {err}")]
603 PackageDirProxyCreateError {
604 #[source]
605 err: fidl::Error,
606 },
607 #[error("ABI compatibility check for `{url}`: {err}")]
608 AbiCompatibilityError {
609 url: Url,
610 #[source]
611 err: CompatibilityCheckError,
612 },
613 #[error(transparent)]
614 Policy(#[from] PolicyError),
615 #[error("`{moniker}` was interrupted")]
616 Aborted { moniker: Moniker },
617}
618
619impl ResolveActionError {
620 fn as_zx_status(&self) -> zx::Status {
621 match self {
622 ResolveActionError::DiscoverActionError { .. }
623 | ResolveActionError::InstanceShutDown { .. }
624 | ResolveActionError::InstanceDestroyed { .. }
625 | ResolveActionError::ComponentAddressParseError { .. }
626 | ResolveActionError::AbiCompatibilityError { .. } => zx::Status::NOT_FOUND,
627 ResolveActionError::ExposeDirError { .. }
628 | ResolveActionError::AddStaticChildError { .. }
629 | ResolveActionError::StructuredConfigError { .. }
630 | ResolveActionError::Aborted { .. }
631 | ResolveActionError::PackageDirProxyCreateError { .. } => zx::Status::INTERNAL,
632 ResolveActionError::ResolverError { err, .. } => err.as_zx_status(),
633 ResolveActionError::Policy(err) => err.as_zx_status(),
634 }
635 }
636}
637
638impl Into<fsys::ResolveError> for ResolveActionError {
640 fn into(self) -> fsys::ResolveError {
641 match self {
642 ResolveActionError::ResolverError {
643 err: ResolverError::PackageNotFound(_), ..
644 } => fsys::ResolveError::PackageNotFound,
645 ResolveActionError::ResolverError {
646 err: ResolverError::ManifestNotFound(_), ..
647 } => fsys::ResolveError::ManifestNotFound,
648 ResolveActionError::InstanceShutDown { .. }
649 | ResolveActionError::InstanceDestroyed { .. } => fsys::ResolveError::InstanceNotFound,
650 ResolveActionError::ExposeDirError { .. }
651 | ResolveActionError::ResolverError { .. }
652 | ResolveActionError::StructuredConfigError { .. }
653 | ResolveActionError::ComponentAddressParseError { .. }
654 | ResolveActionError::AddStaticChildError { .. }
655 | ResolveActionError::DiscoverActionError { .. }
656 | ResolveActionError::AbiCompatibilityError { .. }
657 | ResolveActionError::Aborted { .. }
658 | ResolveActionError::PackageDirProxyCreateError { .. } => fsys::ResolveError::Internal,
659 ResolveActionError::Policy(_) => fsys::ResolveError::PolicyError,
660 }
661 }
662}
663
664impl Into<fsys::StartError> for ResolveActionError {
667 fn into(self) -> fsys::StartError {
668 match self {
669 ResolveActionError::ResolverError {
670 err: ResolverError::PackageNotFound(_), ..
671 } => fsys::StartError::PackageNotFound,
672 ResolveActionError::ResolverError {
673 err: ResolverError::ManifestNotFound(_), ..
674 } => fsys::StartError::ManifestNotFound,
675 ResolveActionError::InstanceShutDown { .. }
676 | ResolveActionError::InstanceDestroyed { .. } => fsys::StartError::InstanceNotFound,
677 ResolveActionError::ExposeDirError { .. }
678 | ResolveActionError::ResolverError { .. }
679 | ResolveActionError::StructuredConfigError { .. }
680 | ResolveActionError::ComponentAddressParseError { .. }
681 | ResolveActionError::AddStaticChildError { .. }
682 | ResolveActionError::DiscoverActionError { .. }
683 | ResolveActionError::AbiCompatibilityError { .. }
684 | ResolveActionError::Aborted { .. }
685 | ResolveActionError::PackageDirProxyCreateError { .. } => fsys::StartError::Internal,
686 ResolveActionError::Policy(_) => fsys::StartError::PolicyError,
687 }
688 }
689}
690
691#[derive(Debug, Clone, Error)]
692pub enum PkgDirError {
693 #[error("no pkg dir found for component")]
694 NoPkgDir,
695 #[error("opening pkg dir failed: {err}")]
696 OpenFailed {
697 #[from]
698 err: zx::Status,
699 },
700}
701
702impl PkgDirError {
703 fn as_zx_status(&self) -> zx::Status {
704 match self {
705 Self::NoPkgDir => zx::Status::NOT_FOUND,
706 Self::OpenFailed { err } => *err,
707 }
708 }
709}
710
711#[derive(Debug, Clone, Error)]
712pub enum ComponentProviderError {
713 #[error("starting source instance:\n\t{err}")]
714 SourceStartError {
715 #[from]
716 err: ActionError,
717 },
718 #[error("opening source instance's outgoing dir:\n\t{err}")]
719 OpenOutgoingDirError {
720 #[from]
721 err: OpenOutgoingDirError,
722 },
723}
724
725impl ComponentProviderError {
726 pub fn as_zx_status(&self) -> zx::Status {
727 match self {
728 Self::SourceStartError { err } => err.as_zx_status(),
729 Self::OpenOutgoingDirError { err } => err.as_zx_status(),
730 }
731 }
732}
733
734#[derive(Debug, Clone, Error)]
735pub enum CapabilityProviderError {
736 #[error("bad path")]
737 BadPath,
738 #[error(transparent)]
739 ComponentInstanceError {
740 #[from]
741 err: ComponentInstanceError,
742 },
743 #[error(transparent)]
744 PkgDirError {
745 #[from]
746 err: PkgDirError,
747 },
748 #[error("event source: {0}")]
749 EventSourceError(#[from] EventSourceError),
750 #[error(transparent)]
751 ComponentProviderError {
752 #[from]
753 err: ComponentProviderError,
754 },
755 #[error("component_manager namespace: {err}")]
756 CmNamespaceError {
757 #[from]
758 err: ClonableError,
759 },
760 #[error("router: {err}")]
761 RouterError {
762 #[from]
763 err: RouterError,
764 },
765 #[error(transparent)]
766 RoutingError(#[from] RoutingError),
767 #[error("opening vfs failed: {0}")]
768 VfsOpenError(#[source] zx::Status),
769}
770
771impl CapabilityProviderError {
772 pub fn as_zx_status(&self) -> zx::Status {
773 match self {
774 Self::BadPath => zx::Status::INVALID_ARGS,
775 Self::ComponentInstanceError { err } => err.as_zx_status(),
776 Self::CmNamespaceError { .. } => zx::Status::INTERNAL,
777 Self::PkgDirError { err } => err.as_zx_status(),
778 Self::EventSourceError(err) => err.as_zx_status(),
779 Self::ComponentProviderError { err } => err.as_zx_status(),
780 Self::RouterError { err } => err.as_zx_status(),
781 Self::RoutingError(err) => err.as_zx_status(),
782 Self::VfsOpenError(err) => *err,
783 }
784 }
785}
786
787#[derive(Debug, Clone, Error)]
788pub enum OpenError {
789 #[error("failed to get default capability provider: {err}")]
790 GetDefaultProviderError {
791 #[source]
793 err: Box<ModelError>,
794 },
795 #[error("no capability provider found")]
796 CapabilityProviderNotFound,
797 #[error("capability provider: {err}")]
798 CapabilityProviderError {
799 #[from]
800 err: CapabilityProviderError,
801 },
802 #[error("opening storage capability: {err}")]
803 OpenStorageError {
804 #[source]
806 err: Box<ModelError>,
807 },
808 #[error("timed out opening capability")]
809 Timeout,
810 #[error("invalid path found")]
811 BadPath,
812 #[error("capability does not support opening: {0}")]
813 DoesNotSupportOpen(ConversionError),
814 #[error("failed to create directory watcher: {err}")]
815 WatcherCreateError {
816 #[from]
817 err: WatcherCreateError,
818 },
819}
820
821impl Explain for OpenError {
822 fn as_zx_status(&self) -> zx::Status {
823 match self {
824 Self::GetDefaultProviderError { err } => err.as_zx_status(),
825 Self::OpenStorageError { err } => err.as_zx_status(),
826 Self::CapabilityProviderError { err } => err.as_zx_status(),
827 Self::CapabilityProviderNotFound => zx::Status::NOT_FOUND,
828 Self::Timeout => zx::Status::TIMED_OUT,
829 Self::BadPath => zx::Status::BAD_PATH,
830 Self::DoesNotSupportOpen(_) => zx::Status::NOT_SUPPORTED,
831 Self::WatcherCreateError { err: WatcherCreateError::SendWatchRequest(_err) } => {
832 zx::Status::PEER_CLOSED
833 }
834 Self::WatcherCreateError { err: WatcherCreateError::WatchError(status) } => *status,
835 Self::WatcherCreateError { err: WatcherCreateError::ChannelConversion(status) } => {
836 *status
837 }
838 }
839 }
840}
841
842impl From<OpenError> for RouterError {
843 fn from(value: OpenError) -> Self {
844 Self::NotFound(Arc::new(value))
845 }
846}
847
848#[derive(Debug, Clone, Error)]
849pub enum StartActionError {
850 #[error("`{moniker}` was shut down")]
851 InstanceShutDown { moniker: Moniker },
852 #[error("`{moniker}` was destroyed")]
853 InstanceDestroyed { moniker: Moniker },
854 #[error("`{moniker}` couldn't resolve during start: {err}")]
855 ResolveActionError {
856 moniker: Moniker,
857 #[source]
858 err: Box<ActionError>,
859 },
860 #[error("runner for `{moniker}` `{runner}` couldn't resolve: {err}")]
861 ResolveRunnerError {
862 moniker: Moniker,
863 runner: Name,
864 #[source]
865 err: Box<RouterError>,
866 },
867 #[error(
868 "`{moniker}` uses `\"on_terminate\": \"reboot\"` but is disallowed by policy:\n\t{err}"
869 )]
870 RebootOnTerminateForbidden {
871 moniker: Moniker,
872 #[source]
873 err: PolicyError,
874 },
875 #[error("creating program input dictionary for `{moniker}`")]
876 InputDictionaryError { moniker: Moniker },
877 #[error("creating namespace: {0}")]
878 CreateNamespaceError(#[from] CreateNamespaceError),
879 #[error("starting program for `{moniker}`: {err}")]
880 StartProgramError {
881 moniker: Moniker,
882 #[source]
883 err: StartError,
884 },
885 #[error("structured configuration for `{moniker}`: {err}")]
886 StructuredConfigError {
887 moniker: Moniker,
888 #[source]
889 err: StructuredConfigError,
890 },
891 #[error("starting eager child of `{moniker}`: {err}")]
892 EagerStartError {
893 moniker: Moniker,
894 #[source]
895 err: Box<ActionError>,
896 },
897 #[error("`{moniker}` was interrupted")]
898 Aborted { moniker: Moniker },
899}
900
901impl StartActionError {
902 fn as_zx_status(&self) -> zx::Status {
903 match self {
904 StartActionError::InstanceDestroyed { .. } | Self::InstanceShutDown { .. } => {
905 zx::Status::NOT_FOUND
906 }
907 StartActionError::StartProgramError { .. }
908 | StartActionError::StructuredConfigError { .. }
909 | StartActionError::EagerStartError { .. } => zx::Status::INTERNAL,
910 StartActionError::RebootOnTerminateForbidden { err, .. } => err.as_zx_status(),
911 StartActionError::ResolveRunnerError { err, .. } => err.as_zx_status(),
912 StartActionError::CreateNamespaceError(err) => err.as_zx_status(),
913 StartActionError::InputDictionaryError { .. } => zx::Status::NOT_FOUND,
914 StartActionError::ResolveActionError { err, .. } => err.as_zx_status(),
915 StartActionError::Aborted { .. } => zx::Status::NOT_FOUND,
916 }
917 }
918}
919
920impl Into<fsys::StartError> for StartActionError {
922 fn into(self) -> fsys::StartError {
923 match self {
924 StartActionError::ResolveActionError { err, .. } => (*err).into(),
925 StartActionError::InstanceDestroyed { .. } => fsys::StartError::InstanceNotFound,
926 StartActionError::InstanceShutDown { .. } => fsys::StartError::InstanceNotFound,
927 _ => fsys::StartError::Internal,
928 }
929 }
930}
931
932impl Into<fcomponent::Error> for StartActionError {
934 fn into(self) -> fcomponent::Error {
935 match self {
936 StartActionError::ResolveActionError { .. } => fcomponent::Error::InstanceCannotResolve,
937 StartActionError::RebootOnTerminateForbidden { .. } => fcomponent::Error::AccessDenied,
938 StartActionError::InstanceShutDown { .. } => fcomponent::Error::InstanceDied,
939 StartActionError::InstanceDestroyed { .. } => fcomponent::Error::InstanceDied,
940 _ => fcomponent::Error::InstanceCannotStart,
941 }
942 }
943}
944
945#[derive(Debug, Clone, Error)]
946pub enum StopActionError {
947 #[error("stopping program: {0}")]
948 ProgramStopError(#[source] StopError),
949 #[error("failed to get top instance")]
950 GetTopInstanceFailed,
951 #[error("failed to get parent instance")]
952 GetParentFailed,
953 #[error("failed to destroy dynamic children: {err}")]
954 DestroyDynamicChildrenFailed { err: Box<ActionError> },
955 #[error("resolution during stop: {err}")]
956 ResolveActionError {
957 #[source]
958 err: Box<ActionError>,
959 },
960 #[error("started while shutdown was ongoing")]
961 ComponentStartedDuringShutdown,
962}
963
964impl Into<fsys::StopError> for StopActionError {
966 fn into(self) -> fsys::StopError {
967 fsys::StopError::Internal
968 }
969}
970
971impl Into<fcomponent::Error> for StopActionError {
972 fn into(self) -> fcomponent::Error {
973 fcomponent::Error::Internal
974 }
975}
976
977#[cfg(test)]
978impl PartialEq for StopActionError {
979 fn eq(&self, other: &Self) -> bool {
980 match (self, other) {
981 (StopActionError::ProgramStopError(_), StopActionError::ProgramStopError(_)) => true,
982 (StopActionError::GetTopInstanceFailed, StopActionError::GetTopInstanceFailed) => true,
983 (StopActionError::GetParentFailed, StopActionError::GetParentFailed) => true,
984 (
985 StopActionError::DestroyDynamicChildrenFailed { .. },
986 StopActionError::DestroyDynamicChildrenFailed { .. },
987 ) => true,
988 (
989 StopActionError::ResolveActionError { .. },
990 StopActionError::ResolveActionError { .. },
991 ) => true,
992 _ => false,
993 }
994 }
995}
996
997#[derive(Debug, Clone, Error)]
998pub enum ShutdownActionError {
999 #[error("child name invalid: {}", err)]
1000 InvalidChildName {
1001 #[from]
1002 err: MonikerError,
1003 },
1004 #[error("cycles detected in graph")]
1005 CyclesDetected {},
1006}
1007
1008#[derive(Debug, Clone, Error)]
1009pub enum DestroyActionError {
1010 #[error("discover during destroy: {}", err)]
1011 DiscoverActionError {
1012 #[from]
1013 err: DiscoverActionError,
1014 },
1015 #[error("shutdown during destroy: {}", err)]
1016 ShutdownFailed {
1017 #[source]
1018 err: Box<ActionError>,
1019 },
1020 #[error("could not find `{moniker}`")]
1021 InstanceNotFound { moniker: Moniker },
1022 #[error("`{moniker}` is not resolved")]
1023 InstanceNotResolved { moniker: Moniker },
1024}
1025
1026impl Into<fcomponent::Error> for DestroyActionError {
1028 fn into(self) -> fcomponent::Error {
1029 match self {
1030 DestroyActionError::InstanceNotFound { .. } => fcomponent::Error::InstanceNotFound,
1031 _ => fcomponent::Error::Internal,
1032 }
1033 }
1034}
1035
1036impl Into<fsys::DestroyError> for DestroyActionError {
1038 fn into(self) -> fsys::DestroyError {
1039 match self {
1040 DestroyActionError::InstanceNotFound { .. } => fsys::DestroyError::InstanceNotFound,
1041 DestroyActionError::InstanceNotResolved { .. } => {
1042 fsys::DestroyError::InstanceNotResolved
1043 }
1044 _ => fsys::DestroyError::Internal,
1045 }
1046 }
1047}
1048
1049#[derive(Debug, Clone, Error)]
1050pub enum UnresolveActionError {
1051 #[error("shutdown during unresolve: {err}")]
1052 ShutdownFailed {
1053 #[from]
1054 err: StopActionError,
1055 },
1056 #[error("`{moniker}` cannot be unresolved while it is running")]
1057 InstanceRunning { moniker: Moniker },
1058 #[error("`{moniker}` was destroyed")]
1059 InstanceDestroyed { moniker: Moniker },
1060}
1061
1062impl Into<fsys::UnresolveError> for UnresolveActionError {
1064 fn into(self) -> fsys::UnresolveError {
1065 match self {
1066 UnresolveActionError::InstanceDestroyed { .. } => {
1067 fsys::UnresolveError::InstanceNotFound
1068 }
1069 _ => fsys::UnresolveError::Internal,
1070 }
1071 }
1072}
1073
1074#[derive(Debug, Clone, Error)]
1075pub enum CreateNamespaceError {
1076 #[error("failed to clone pkg dir for {moniker}: {err}")]
1077 ClonePkgDirFailed {
1078 moniker: Moniker,
1079 #[source]
1080 err: fuchsia_fs::node::CloneError,
1081 },
1082
1083 #[error("use decl without path cannot be installed into the namespace for {moniker}: {decl:?}")]
1084 UseDeclWithoutPath { moniker: Moniker, decl: UseDecl },
1085
1086 #[error("instance not in index: {0}")]
1087 InstanceNotInInstanceIdIndex(#[from] RoutingError),
1088
1089 #[error("building namespace for {moniker}: {err}")]
1090 BuildNamespaceError {
1091 moniker: Moniker,
1092 #[source]
1093 err: serve_processargs::BuildNamespaceError,
1094 },
1095
1096 #[error("failed to convert namespace into directory for {moniker}: {err}")]
1097 ConvertToDirectory {
1098 moniker: Moniker,
1099 #[source]
1100 err: ClonableError,
1101 },
1102
1103 #[error(transparent)]
1104 ComponentInstanceError(#[from] ComponentInstanceError),
1105}
1106
1107impl CreateNamespaceError {
1108 fn as_zx_status(&self) -> zx::Status {
1109 match self {
1110 Self::ClonePkgDirFailed { .. } => zx::Status::INTERNAL,
1111 Self::UseDeclWithoutPath { .. } => zx::Status::NOT_FOUND,
1112 Self::InstanceNotInInstanceIdIndex(err) => err.as_zx_status(),
1113 Self::BuildNamespaceError { .. } => zx::Status::NOT_FOUND,
1114 Self::ConvertToDirectory { .. } => zx::Status::INTERNAL,
1115 Self::ComponentInstanceError(err) => err.as_zx_status(),
1116 }
1117 }
1118}
1119
1120#[derive(Debug, Clone, Error)]
1121pub enum EventSourceError {
1122 #[error(transparent)]
1123 ComponentInstance(#[from] ComponentInstanceError),
1124 #[error(transparent)]
1125 Model(#[from] Box<ModelError>),
1127 #[error("event stream already consumed")]
1128 AlreadyConsumed,
1129}
1130
1131impl EventSourceError {
1132 fn as_zx_status(&self) -> zx::Status {
1133 match self {
1134 Self::ComponentInstance(err) => err.as_zx_status(),
1135 Self::Model(err) => err.as_zx_status(),
1136 Self::AlreadyConsumed => zx::Status::INTERNAL,
1137 }
1138 }
1139}
1140
1141#[derive(Debug, Error, Clone)]
1142pub enum EventsError {
1143 #[error("capability_requested event streams cannot be taken twice")]
1144 CapabilityRequestedStreamTaken,
1145
1146 #[error("model not available")]
1147 ModelNotAvailable,
1148
1149 #[error("instance shut down")]
1150 InstanceShutdown,
1151
1152 #[error("instance destroyed")]
1153 InstanceDestroyed,
1154
1155 #[error("registry not found")]
1156 RegistryNotFound,
1157
1158 #[error("event `{event_name}` appears more than once in a subscription request")]
1159 DuplicateEvent { event_name: Name },
1160
1161 #[error("events not available for subscription: `{names:?}`")]
1162 NotAvailable { names: Vec<Name> },
1163}
1164
1165impl EventsError {
1166 pub fn duplicate_event(event_name: Name) -> Self {
1167 Self::DuplicateEvent { event_name }
1168 }
1169
1170 pub fn not_available(names: Vec<Name>) -> Self {
1171 Self::NotAvailable { names }
1172 }
1173}
1174
1175#[derive(Debug, Error, Clone)]
1177pub enum StorageError {
1178 #[error("opening directory from `{dir_source_moniker:?}` at `{dir_source_path}`:\n\t{err}")]
1179 OpenRoot {
1180 dir_source_moniker: Option<Moniker>,
1181 dir_source_path: cm_types::Path,
1182 #[source]
1183 err: ClonableError,
1184 },
1185 #[error(
1186 "opening isolated storage from `{dir_source_moniker:?}`'s for `{moniker}` at `{dir_source_path}` (instance_id={instance_id:?}):\n\t{err}"
1187 )]
1188 Open {
1189 dir_source_moniker: Option<Moniker>,
1190 dir_source_path: cm_types::Path,
1191 moniker: Moniker,
1192 instance_id: Option<InstanceId>,
1193 #[source]
1194 err: ClonableError,
1195 },
1196 #[error(
1197 "opening isolated storage from `{dir_source_moniker:?}` at `{dir_source_path}` for {instance_id}:\n\t{err}"
1198 )]
1199 OpenById {
1200 dir_source_moniker: Option<Moniker>,
1201 dir_source_path: cm_types::Path,
1202 instance_id: InstanceId,
1203 #[source]
1204 err: ClonableError,
1205 },
1206 #[error(
1207 "removing isolated storage from {dir_source_moniker:?} at `{dir_source_path}` for `{moniker}` (instance_id={instance_id:?}):n\t{err} "
1208 )]
1209 Remove {
1210 dir_source_moniker: Option<Moniker>,
1211 dir_source_path: cm_types::Path,
1212 moniker: Moniker,
1213 instance_id: Option<InstanceId>,
1214 #[source]
1215 err: ClonableError,
1216 },
1217 #[error("storage path for `{moniker}` (instance_id={instance_id:?}) is invalid")]
1218 InvalidStoragePath { moniker: Moniker, instance_id: Option<InstanceId> },
1219}
1220
1221impl StorageError {
1222 pub fn open_root(
1223 dir_source_moniker: Option<Moniker>,
1224 dir_source_path: cm_types::Path,
1225 err: impl Into<Error>,
1226 ) -> Self {
1227 Self::OpenRoot { dir_source_moniker, dir_source_path, err: err.into().into() }
1228 }
1229
1230 pub fn open(
1231 dir_source_moniker: Option<Moniker>,
1232 dir_source_path: cm_types::Path,
1233 moniker: Moniker,
1234 instance_id: Option<InstanceId>,
1235 err: impl Into<Error>,
1236 ) -> Self {
1237 Self::Open {
1238 dir_source_moniker,
1239 dir_source_path,
1240 moniker,
1241 instance_id,
1242 err: err.into().into(),
1243 }
1244 }
1245
1246 pub fn open_by_id(
1247 dir_source_moniker: Option<Moniker>,
1248 dir_source_path: cm_types::Path,
1249 instance_id: InstanceId,
1250 err: impl Into<Error>,
1251 ) -> Self {
1252 Self::OpenById { dir_source_moniker, dir_source_path, instance_id, err: err.into().into() }
1253 }
1254
1255 pub fn remove(
1256 dir_source_moniker: Option<Moniker>,
1257 dir_source_path: cm_types::Path,
1258 moniker: Moniker,
1259 instance_id: Option<InstanceId>,
1260 err: impl Into<Error>,
1261 ) -> Self {
1262 Self::Remove {
1263 dir_source_moniker,
1264 dir_source_path,
1265 moniker,
1266 instance_id,
1267 err: err.into().into(),
1268 }
1269 }
1270
1271 pub fn invalid_storage_path(moniker: Moniker, instance_id: Option<InstanceId>) -> Self {
1272 Self::InvalidStoragePath { moniker, instance_id }
1273 }
1274}
1275
1276#[derive(Error, Debug, Clone)]
1277pub enum StartError {
1278 #[error("serving namespace: {0}")]
1279 ServeNamespace(BuildNamespaceError),
1280}
1281
1282#[derive(Error, Debug, Clone)]
1283pub enum StopError {
1284 #[error("internal: {0}")]
1286 Internal(fidl::Error),
1287}