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 runtime_capabilities::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: Box<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: Box<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: Box<ResolverError>,
576 },
577 #[error("resolve failed for `{url}`:\n\t{err}")]
578 ResolverError {
579 url: Url,
580 #[source]
581 err: Box<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: Box<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 { err, .. } => match *err {
643 ResolverError::PackageNotFound(_) => fsys::ResolveError::PackageNotFound,
644 ResolverError::ManifestNotFound(_) => fsys::ResolveError::ManifestNotFound,
645 _ => fsys::ResolveError::Internal,
646 },
647 ResolveActionError::InstanceShutDown { .. }
648 | ResolveActionError::InstanceDestroyed { .. } => fsys::ResolveError::InstanceNotFound,
649 ResolveActionError::ExposeDirError { .. }
650 | ResolveActionError::StructuredConfigError { .. }
651 | ResolveActionError::ComponentAddressParseError { .. }
652 | ResolveActionError::AddStaticChildError { .. }
653 | ResolveActionError::DiscoverActionError { .. }
654 | ResolveActionError::AbiCompatibilityError { .. }
655 | ResolveActionError::Aborted { .. }
656 | ResolveActionError::PackageDirProxyCreateError { .. } => fsys::ResolveError::Internal,
657 ResolveActionError::Policy(_) => fsys::ResolveError::PolicyError,
658 }
659 }
660}
661
662impl Into<fsys::StartError> for ResolveActionError {
665 fn into(self) -> fsys::StartError {
666 match self {
667 ResolveActionError::ResolverError { err, .. } => match *err {
668 ResolverError::PackageNotFound(_) => fsys::StartError::PackageNotFound,
669 ResolverError::ManifestNotFound(_) => fsys::StartError::ManifestNotFound,
670 _ => fsys::StartError::Internal,
671 },
672 ResolveActionError::InstanceShutDown { .. }
673 | ResolveActionError::InstanceDestroyed { .. } => fsys::StartError::InstanceNotFound,
674 ResolveActionError::ExposeDirError { .. }
675 | ResolveActionError::StructuredConfigError { .. }
676 | ResolveActionError::ComponentAddressParseError { .. }
677 | ResolveActionError::AddStaticChildError { .. }
678 | ResolveActionError::DiscoverActionError { .. }
679 | ResolveActionError::AbiCompatibilityError { .. }
680 | ResolveActionError::Aborted { .. }
681 | ResolveActionError::PackageDirProxyCreateError { .. } => fsys::StartError::Internal,
682 ResolveActionError::Policy(_) => fsys::StartError::PolicyError,
683 }
684 }
685}
686
687#[derive(Debug, Clone, Error)]
688pub enum PkgDirError {
689 #[error("no pkg dir found for component")]
690 NoPkgDir,
691 #[error("opening pkg dir failed: {err}")]
692 OpenFailed {
693 #[from]
694 err: zx::Status,
695 },
696}
697
698impl PkgDirError {
699 fn as_zx_status(&self) -> zx::Status {
700 match self {
701 Self::NoPkgDir => zx::Status::NOT_FOUND,
702 Self::OpenFailed { err } => *err,
703 }
704 }
705}
706
707#[derive(Debug, Clone, Error)]
708pub enum ComponentProviderError {
709 #[error("starting source instance:\n\t{err}")]
710 SourceStartError {
711 #[from]
712 err: ActionError,
713 },
714 #[error("opening source instance's outgoing dir:\n\t{err}")]
715 OpenOutgoingDirError {
716 #[from]
717 err: OpenOutgoingDirError,
718 },
719}
720
721impl ComponentProviderError {
722 pub fn as_zx_status(&self) -> zx::Status {
723 match self {
724 Self::SourceStartError { err } => err.as_zx_status(),
725 Self::OpenOutgoingDirError { err } => err.as_zx_status(),
726 }
727 }
728}
729
730#[derive(Debug, Clone, Error)]
731pub enum CapabilityProviderError {
732 #[error("bad path")]
733 BadPath,
734 #[error(transparent)]
735 ComponentInstanceError {
736 #[from]
737 err: ComponentInstanceError,
738 },
739 #[error(transparent)]
740 PkgDirError {
741 #[from]
742 err: PkgDirError,
743 },
744 #[error("event source: {0}")]
745 EventSourceError(#[from] EventSourceError),
746 #[error(transparent)]
747 ComponentProviderError {
748 #[from]
749 err: ComponentProviderError,
750 },
751 #[error("component_manager namespace: {err}")]
752 CmNamespaceError {
753 #[from]
754 err: ClonableError,
755 },
756 #[error("router: {err}")]
757 RouterError {
758 #[from]
759 err: RouterError,
760 },
761 #[error(transparent)]
762 RoutingError(#[from] RoutingError),
763 #[error("opening vfs failed: {0}")]
764 VfsOpenError(#[source] zx::Status),
765}
766
767impl CapabilityProviderError {
768 pub fn as_zx_status(&self) -> zx::Status {
769 match self {
770 Self::BadPath => zx::Status::INVALID_ARGS,
771 Self::ComponentInstanceError { err } => err.as_zx_status(),
772 Self::CmNamespaceError { .. } => zx::Status::INTERNAL,
773 Self::PkgDirError { err } => err.as_zx_status(),
774 Self::EventSourceError(err) => err.as_zx_status(),
775 Self::ComponentProviderError { err } => err.as_zx_status(),
776 Self::RouterError { err } => err.as_zx_status(),
777 Self::RoutingError(err) => err.as_zx_status(),
778 Self::VfsOpenError(err) => *err,
779 }
780 }
781}
782
783#[derive(Debug, Clone, Error)]
784pub enum OpenError {
785 #[error("failed to get default capability provider: {err}")]
786 GetDefaultProviderError {
787 #[source]
789 err: Box<ModelError>,
790 },
791 #[error("no capability provider found")]
792 CapabilityProviderNotFound,
793 #[error("capability provider: {err}")]
794 CapabilityProviderError {
795 #[from]
796 err: CapabilityProviderError,
797 },
798 #[error("opening storage capability: {err}")]
799 OpenStorageError {
800 #[source]
802 err: Box<ModelError>,
803 },
804 #[error("timed out opening capability")]
805 Timeout,
806 #[error("invalid path found")]
807 BadPath,
808 #[error("capability does not support opening: {0}")]
809 DoesNotSupportOpen(ConversionError),
810 #[error("failed to create directory watcher: {err}")]
811 WatcherCreateError {
812 #[from]
813 err: WatcherCreateError,
814 },
815}
816
817impl Explain for OpenError {
818 fn as_zx_status(&self) -> zx::Status {
819 match self {
820 Self::GetDefaultProviderError { err } => err.as_zx_status(),
821 Self::OpenStorageError { err } => err.as_zx_status(),
822 Self::CapabilityProviderError { err } => err.as_zx_status(),
823 Self::CapabilityProviderNotFound => zx::Status::NOT_FOUND,
824 Self::Timeout => zx::Status::TIMED_OUT,
825 Self::BadPath => zx::Status::BAD_PATH,
826 Self::DoesNotSupportOpen(_) => zx::Status::NOT_SUPPORTED,
827 Self::WatcherCreateError { err: WatcherCreateError::SendWatchRequest(_err) } => {
828 zx::Status::PEER_CLOSED
829 }
830 Self::WatcherCreateError { err: WatcherCreateError::WatchError(status) } => *status,
831 Self::WatcherCreateError { err: WatcherCreateError::ChannelConversion(status) } => {
832 *status
833 }
834 }
835 }
836}
837
838impl From<OpenError> for RouterError {
839 fn from(value: OpenError) -> Self {
840 Self::NotFound(Arc::new(value))
841 }
842}
843
844#[derive(Debug, Clone, Error)]
845pub enum StartActionError {
846 #[error("`{moniker}` was shut down")]
847 InstanceShutDown { moniker: Moniker },
848 #[error("`{moniker}` was destroyed")]
849 InstanceDestroyed { moniker: Moniker },
850 #[error("`{moniker}` couldn't resolve during start: {err}")]
851 ResolveActionError {
852 moniker: Moniker,
853 #[source]
854 err: Box<ActionError>,
855 },
856 #[error("runner for `{moniker}` `{runner}` couldn't resolve: {err}")]
857 ResolveRunnerError {
858 moniker: Moniker,
859 runner: Name,
860 #[source]
861 err: Box<RouterError>,
862 },
863 #[error(
864 "`{moniker}` uses `\"on_terminate\": \"reboot\"` but is disallowed by policy:\n\t{err}"
865 )]
866 RebootOnTerminateForbidden {
867 moniker: Moniker,
868 #[source]
869 err: PolicyError,
870 },
871 #[error("creating program input dictionary for `{moniker}`")]
872 InputDictionaryError { moniker: Moniker },
873 #[error("creating namespace: {0}")]
874 CreateNamespaceError(#[from] CreateNamespaceError),
875 #[error("starting program for `{moniker}`: {err}")]
876 StartProgramError {
877 moniker: Moniker,
878 #[source]
879 err: StartError,
880 },
881 #[error("structured configuration for `{moniker}`: {err}")]
882 StructuredConfigError {
883 moniker: Moniker,
884 #[source]
885 err: StructuredConfigError,
886 },
887 #[error("starting eager child of `{moniker}`: {err}")]
888 EagerStartError {
889 moniker: Moniker,
890 #[source]
891 err: Box<ActionError>,
892 },
893 #[error("`{moniker}` was interrupted")]
894 Aborted { moniker: Moniker },
895}
896
897impl StartActionError {
898 fn as_zx_status(&self) -> zx::Status {
899 match self {
900 StartActionError::InstanceDestroyed { .. } | Self::InstanceShutDown { .. } => {
901 zx::Status::NOT_FOUND
902 }
903 StartActionError::StartProgramError { .. }
904 | StartActionError::StructuredConfigError { .. }
905 | StartActionError::EagerStartError { .. } => zx::Status::INTERNAL,
906 StartActionError::RebootOnTerminateForbidden { err, .. } => err.as_zx_status(),
907 StartActionError::ResolveRunnerError { err, .. } => err.as_zx_status(),
908 StartActionError::CreateNamespaceError(err) => err.as_zx_status(),
909 StartActionError::InputDictionaryError { .. } => zx::Status::NOT_FOUND,
910 StartActionError::ResolveActionError { err, .. } => err.as_zx_status(),
911 StartActionError::Aborted { .. } => zx::Status::NOT_FOUND,
912 }
913 }
914}
915
916impl Into<fsys::StartError> for StartActionError {
918 fn into(self) -> fsys::StartError {
919 match self {
920 StartActionError::ResolveActionError { err, .. } => (*err).into(),
921 StartActionError::InstanceDestroyed { .. } => fsys::StartError::InstanceNotFound,
922 StartActionError::InstanceShutDown { .. } => fsys::StartError::InstanceNotFound,
923 _ => fsys::StartError::Internal,
924 }
925 }
926}
927
928impl Into<fcomponent::Error> for StartActionError {
930 fn into(self) -> fcomponent::Error {
931 match self {
932 StartActionError::ResolveActionError { .. } => fcomponent::Error::InstanceCannotResolve,
933 StartActionError::RebootOnTerminateForbidden { .. } => fcomponent::Error::AccessDenied,
934 StartActionError::InstanceShutDown { .. } => fcomponent::Error::InstanceDied,
935 StartActionError::InstanceDestroyed { .. } => fcomponent::Error::InstanceDied,
936 _ => fcomponent::Error::InstanceCannotStart,
937 }
938 }
939}
940
941#[derive(Debug, Clone, Error)]
942pub enum StopActionError {
943 #[error("stopping program: {0}")]
944 ProgramStopError(#[source] StopError),
945 #[error("failed to get top instance")]
946 GetTopInstanceFailed,
947 #[error("failed to get parent instance")]
948 GetParentFailed,
949 #[error("failed to destroy dynamic children: {err}")]
950 DestroyDynamicChildrenFailed { err: Box<ActionError> },
951 #[error("resolution during stop: {err}")]
952 ResolveActionError {
953 #[source]
954 err: Box<ActionError>,
955 },
956 #[error("started while shutdown was ongoing")]
957 ComponentStartedDuringShutdown,
958}
959
960impl Into<fsys::StopError> for StopActionError {
962 fn into(self) -> fsys::StopError {
963 fsys::StopError::Internal
964 }
965}
966
967impl Into<fcomponent::Error> for StopActionError {
968 fn into(self) -> fcomponent::Error {
969 fcomponent::Error::Internal
970 }
971}
972
973#[cfg(test)]
974impl PartialEq for StopActionError {
975 fn eq(&self, other: &Self) -> bool {
976 match (self, other) {
977 (StopActionError::ProgramStopError(_), StopActionError::ProgramStopError(_)) => true,
978 (StopActionError::GetTopInstanceFailed, StopActionError::GetTopInstanceFailed) => true,
979 (StopActionError::GetParentFailed, StopActionError::GetParentFailed) => true,
980 (
981 StopActionError::DestroyDynamicChildrenFailed { .. },
982 StopActionError::DestroyDynamicChildrenFailed { .. },
983 ) => true,
984 (
985 StopActionError::ResolveActionError { .. },
986 StopActionError::ResolveActionError { .. },
987 ) => true,
988 _ => false,
989 }
990 }
991}
992
993#[derive(Debug, Clone, Error)]
994pub enum ShutdownActionError {
995 #[error("child name invalid: {}", err)]
996 InvalidChildName {
997 #[from]
998 err: MonikerError,
999 },
1000 #[error("cycles detected in graph")]
1001 CyclesDetected {},
1002}
1003
1004#[derive(Debug, Clone, Error)]
1005pub enum DestroyActionError {
1006 #[error("discover during destroy: {}", err)]
1007 DiscoverActionError {
1008 #[from]
1009 err: DiscoverActionError,
1010 },
1011 #[error("shutdown during destroy: {}", err)]
1012 ShutdownFailed {
1013 #[source]
1014 err: Box<ActionError>,
1015 },
1016 #[error("could not find `{moniker}`")]
1017 InstanceNotFound { moniker: Moniker },
1018 #[error("`{moniker}` is not resolved")]
1019 InstanceNotResolved { moniker: Moniker },
1020}
1021
1022impl Into<fcomponent::Error> for DestroyActionError {
1024 fn into(self) -> fcomponent::Error {
1025 match self {
1026 DestroyActionError::InstanceNotFound { .. } => fcomponent::Error::InstanceNotFound,
1027 _ => fcomponent::Error::Internal,
1028 }
1029 }
1030}
1031
1032impl Into<fsys::DestroyError> for DestroyActionError {
1034 fn into(self) -> fsys::DestroyError {
1035 match self {
1036 DestroyActionError::InstanceNotFound { .. } => fsys::DestroyError::InstanceNotFound,
1037 DestroyActionError::InstanceNotResolved { .. } => {
1038 fsys::DestroyError::InstanceNotResolved
1039 }
1040 _ => fsys::DestroyError::Internal,
1041 }
1042 }
1043}
1044
1045#[derive(Debug, Clone, Error)]
1046pub enum UnresolveActionError {
1047 #[error("shutdown during unresolve: {err}")]
1048 ShutdownFailed {
1049 #[from]
1050 err: StopActionError,
1051 },
1052 #[error("`{moniker}` cannot be unresolved while it is running")]
1053 InstanceRunning { moniker: Moniker },
1054 #[error("`{moniker}` was destroyed")]
1055 InstanceDestroyed { moniker: Moniker },
1056}
1057
1058impl Into<fsys::UnresolveError> for UnresolveActionError {
1060 fn into(self) -> fsys::UnresolveError {
1061 match self {
1062 UnresolveActionError::InstanceDestroyed { .. } => {
1063 fsys::UnresolveError::InstanceNotFound
1064 }
1065 _ => fsys::UnresolveError::Internal,
1066 }
1067 }
1068}
1069
1070#[derive(Debug, Clone, Error)]
1071pub enum CreateNamespaceError {
1072 #[error("failed to clone pkg dir for {moniker}: {err}")]
1073 ClonePkgDirFailed {
1074 moniker: Moniker,
1075 #[source]
1076 err: fuchsia_fs::node::CloneError,
1077 },
1078
1079 #[error("use decl without path cannot be installed into the namespace for {moniker}: {decl:?}")]
1080 UseDeclWithoutPath { moniker: Moniker, decl: UseDecl },
1081
1082 #[error("instance not in index: {0}")]
1083 InstanceNotInInstanceIdIndex(#[from] RoutingError),
1084
1085 #[error("building namespace for {moniker}: {err}")]
1086 BuildNamespaceError {
1087 moniker: Moniker,
1088 #[source]
1089 err: serve_processargs::BuildNamespaceError,
1090 },
1091
1092 #[error("failed to convert namespace into directory for {moniker}: {err}")]
1093 ConvertToDirectory {
1094 moniker: Moniker,
1095 #[source]
1096 err: ClonableError,
1097 },
1098
1099 #[error(transparent)]
1100 ComponentInstanceError(#[from] ComponentInstanceError),
1101}
1102
1103impl CreateNamespaceError {
1104 fn as_zx_status(&self) -> zx::Status {
1105 match self {
1106 Self::ClonePkgDirFailed { .. } => zx::Status::INTERNAL,
1107 Self::UseDeclWithoutPath { .. } => zx::Status::NOT_FOUND,
1108 Self::InstanceNotInInstanceIdIndex(err) => err.as_zx_status(),
1109 Self::BuildNamespaceError { .. } => zx::Status::NOT_FOUND,
1110 Self::ConvertToDirectory { .. } => zx::Status::INTERNAL,
1111 Self::ComponentInstanceError(err) => err.as_zx_status(),
1112 }
1113 }
1114}
1115
1116#[derive(Debug, Clone, Error)]
1117pub enum EventSourceError {
1118 #[error(transparent)]
1119 ComponentInstance(#[from] ComponentInstanceError),
1120 #[error(transparent)]
1121 Model(#[from] Box<ModelError>),
1123 #[error("event stream already consumed")]
1124 AlreadyConsumed,
1125}
1126
1127impl EventSourceError {
1128 fn as_zx_status(&self) -> zx::Status {
1129 match self {
1130 Self::ComponentInstance(err) => err.as_zx_status(),
1131 Self::Model(err) => err.as_zx_status(),
1132 Self::AlreadyConsumed => zx::Status::INTERNAL,
1133 }
1134 }
1135}
1136
1137#[derive(Debug, Error, Clone)]
1138pub enum EventsError {
1139 #[error("capability_requested event streams cannot be taken twice")]
1140 CapabilityRequestedStreamTaken,
1141
1142 #[error("model not available")]
1143 ModelNotAvailable,
1144
1145 #[error("instance shut down")]
1146 InstanceShutdown,
1147
1148 #[error("instance destroyed")]
1149 InstanceDestroyed,
1150
1151 #[error("registry not found")]
1152 RegistryNotFound,
1153
1154 #[error("event `{event_name}` appears more than once in a subscription request")]
1155 DuplicateEvent { event_name: Name },
1156
1157 #[error("events not available for subscription: `{names:?}`")]
1158 NotAvailable { names: Vec<Name> },
1159}
1160
1161impl EventsError {
1162 pub fn duplicate_event(event_name: Name) -> Self {
1163 Self::DuplicateEvent { event_name }
1164 }
1165
1166 pub fn not_available(names: Vec<Name>) -> Self {
1167 Self::NotAvailable { names }
1168 }
1169}
1170
1171#[derive(Debug, Error, Clone)]
1173pub enum StorageError {
1174 #[error("opening directory from `{dir_source_moniker:?}` at `{dir_source_path}`:\n\t{err}")]
1175 OpenRoot {
1176 dir_source_moniker: Option<Moniker>,
1177 dir_source_path: cm_types::Path,
1178 #[source]
1179 err: ClonableError,
1180 },
1181 #[error(
1182 "opening isolated storage from `{dir_source_moniker:?}`'s for `{moniker}` at `{dir_source_path}` (instance_id={instance_id:?}):\n\t{err}"
1183 )]
1184 Open {
1185 dir_source_moniker: Option<Moniker>,
1186 dir_source_path: cm_types::Path,
1187 moniker: Moniker,
1188 instance_id: Option<InstanceId>,
1189 #[source]
1190 err: ClonableError,
1191 },
1192 #[error(
1193 "opening isolated storage from `{dir_source_moniker:?}` at `{dir_source_path}` for {instance_id}:\n\t{err}"
1194 )]
1195 OpenById {
1196 dir_source_moniker: Option<Moniker>,
1197 dir_source_path: cm_types::Path,
1198 instance_id: InstanceId,
1199 #[source]
1200 err: ClonableError,
1201 },
1202 #[error(
1203 "removing isolated storage from {dir_source_moniker:?} at `{dir_source_path}` for `{moniker}` (instance_id={instance_id:?}):n\t{err} "
1204 )]
1205 Remove {
1206 dir_source_moniker: Option<Moniker>,
1207 dir_source_path: cm_types::Path,
1208 moniker: Moniker,
1209 instance_id: Option<InstanceId>,
1210 #[source]
1211 err: ClonableError,
1212 },
1213 #[error("storage path for `{moniker}` (instance_id={instance_id:?}) is invalid")]
1214 InvalidStoragePath { moniker: Moniker, instance_id: Option<InstanceId> },
1215}
1216
1217impl StorageError {
1218 pub fn open_root(
1219 dir_source_moniker: Option<Moniker>,
1220 dir_source_path: cm_types::Path,
1221 err: impl Into<Error>,
1222 ) -> Self {
1223 Self::OpenRoot { dir_source_moniker, dir_source_path, err: err.into().into() }
1224 }
1225
1226 pub fn open(
1227 dir_source_moniker: Option<Moniker>,
1228 dir_source_path: cm_types::Path,
1229 moniker: Moniker,
1230 instance_id: Option<InstanceId>,
1231 err: impl Into<Error>,
1232 ) -> Self {
1233 Self::Open {
1234 dir_source_moniker,
1235 dir_source_path,
1236 moniker,
1237 instance_id,
1238 err: err.into().into(),
1239 }
1240 }
1241
1242 pub fn open_by_id(
1243 dir_source_moniker: Option<Moniker>,
1244 dir_source_path: cm_types::Path,
1245 instance_id: InstanceId,
1246 err: impl Into<Error>,
1247 ) -> Self {
1248 Self::OpenById { dir_source_moniker, dir_source_path, instance_id, err: err.into().into() }
1249 }
1250
1251 pub fn remove(
1252 dir_source_moniker: Option<Moniker>,
1253 dir_source_path: cm_types::Path,
1254 moniker: Moniker,
1255 instance_id: Option<InstanceId>,
1256 err: impl Into<Error>,
1257 ) -> Self {
1258 Self::Remove {
1259 dir_source_moniker,
1260 dir_source_path,
1261 moniker,
1262 instance_id,
1263 err: err.into().into(),
1264 }
1265 }
1266
1267 pub fn invalid_storage_path(moniker: Moniker, instance_id: Option<InstanceId>) -> Self {
1268 Self::InvalidStoragePath { moniker, instance_id }
1269 }
1270}
1271
1272#[derive(Error, Debug, Clone)]
1273pub enum StartError {
1274 #[error("serving namespace: {0}")]
1275 ServeNamespace(BuildNamespaceError),
1276}
1277
1278#[derive(Error, Debug, Clone)]
1279pub enum StopError {
1280 #[error("internal: {0}")]
1282 Internal(fidl::Error),
1283}