1use crate::{
4 component::compute::backend::HealthcheckCreationError, handoff::HandoffInfo,
5 wiggle_abi::types::FastlyStatus,
6};
7use hyper::StatusCode;
8use std::error::Error as StdError;
9use std::io;
10use url::Url;
11use wiggle::GuestError;
12
13#[derive(Debug, thiserror::Error)]
14#[non_exhaustive]
15pub enum Error {
16 #[error("Buffer length error: {buf} too long to fit in {len}")]
18 BufferLengthError {
19 buf: &'static str,
20 len: &'static str,
21 },
22
23 #[error("Fatal error: [{0}]")]
26 FatalError(String),
27
28 #[error("Expected a valid Wasm file")]
30 FileFormat,
31
32 #[error("Expected a valid wastime's profiling strategy")]
33 ProfilingStrategy,
34
35 #[error(transparent)]
36 FastlyConfig(#[from] FastlyConfigError),
37
38 #[error("Could not determine address from backend URL: {0}")]
39 BackendUrl(Url),
40
41 #[error("Guest error: [{0}]")]
46 GuestError(#[from] wiggle::GuestError),
47
48 #[error(transparent)]
49 HandleError(#[from] HandleError),
50
51 #[error(transparent)]
52 HyperError(#[from] hyper::Error),
53
54 #[error(transparent)]
55 HealthcheckCreationError(#[from] HealthcheckCreationError),
56
57 #[error("Backend connection error for '{backend_name}' ({uri}): {source}")]
58 BackendConnectionError {
59 backend_name: String,
60 uri: String,
61 #[source]
62 source: hyper::Error,
63 },
64
65 #[error(transparent)]
66 Infallible(#[from] std::convert::Infallible),
67
68 #[error("Invalid argument given")]
70 InvalidArgument,
71
72 #[error(transparent)]
73 InvalidHeaderName(#[from] http::header::InvalidHeaderName),
74
75 #[error(transparent)]
76 InvalidHeaderValue(#[from] http::header::InvalidHeaderValue),
77
78 #[error(transparent)]
79 InvalidMethod(#[from] http::method::InvalidMethod),
80
81 #[error(transparent)]
82 InvalidStatusCode(#[from] http::status::InvalidStatusCode),
83
84 #[error(transparent)]
85 InvalidUri(#[from] http::uri::InvalidUri),
86
87 #[error(transparent)]
88 IoError(#[from] std::io::Error),
89
90 #[error("Limit exceeded: {msg}")]
91 LimitExceeded { msg: &'static str },
92
93 #[error("Missing downstream metadata for request")]
94 MissingDownstreamMetadata,
95
96 #[error(transparent)]
97 Other(#[from] anyhow::Error),
98
99 #[error("Unsupported operation: {msg}")]
100 Unsupported { msg: &'static str },
101
102 #[error("Downstream response already sending")]
104 DownstreamRespSending,
105
106 #[error("Unexpected error sending a chunk to a streaming body")]
107 StreamingChunkSend,
108
109 #[error("Unknown backend: {0}")]
110 UnknownBackend(String),
111
112 #[error(transparent)]
113 DictionaryError(#[from] crate::wiggle_abi::DictionaryError),
114
115 #[error(transparent)]
116 DeviceDetectionError(#[from] crate::wiggle_abi::DeviceDetectionError),
117
118 #[error(transparent)]
119 ObjectStoreError(#[from] crate::object_store::ObjectStoreError),
120
121 #[error(transparent)]
122 KvStoreError(#[from] crate::object_store::KvStoreError),
123
124 #[error(transparent)]
125 SecretStoreError(#[from] crate::wiggle_abi::SecretStoreError),
126
127 #[error{"Expected UTF-8"}]
128 Utf8Expected(#[from] std::str::Utf8Error),
129
130 #[error{"Unsupported ABI version"}]
131 AbiVersionMismatch,
132
133 #[error(transparent)]
134 DownstreamRequestError(#[from] DownstreamRequestError),
135
136 #[error("{0} is not currently supported for local testing")]
137 NotAvailable(&'static str),
138
139 #[error("Could not load native certificates: {0}")]
140 BadCerts(std::io::Error),
141
142 #[error("No CA certificates available")]
143 TlsNoCAAvailable,
144
145 #[error("No valid CA certificates found in provided certificate bundle")]
146 TlsNoValidCACerts,
147
148 #[error("Invalid or missing host for TLS connection")]
149 TlsInvalidHost,
150
151 #[error("TLS certificate validation failed")]
152 TlsCertificateValidationFailed,
153
154 #[error("Could not generate new backend name from '{0}'")]
155 BackendNameRegistryError(String),
156
157 #[error(transparent)]
158 HttpError(#[from] http::Error),
159
160 #[error("Object Store '{0}' does not exist")]
161 UnknownObjectStore(String),
162
163 #[error("Invalid Object Store `key` value used: {0}.")]
164 ObjectStoreKeyValidationError(#[from] crate::object_store::KeyValidationError),
165
166 #[error("Unfinished streaming body")]
167 UnfinishedStreamingBody,
168
169 #[error("Shared memory not supported yet")]
170 SharedMemory,
171
172 #[error("Value absent from structure")]
173 ValueAbsent,
174
175 #[error("String conversion error")]
176 ToStr(#[from] http::header::ToStrError),
177
178 #[error("invalid client certificate")]
179 InvalidClientCert(#[from] crate::config::ClientCertError),
180
181 #[error("Invalid response to ALPN request; wanted '{0}', got '{1}'")]
182 InvalidAlpnResponse(&'static str, String),
183
184 #[error("Resource temporarily unavailable")]
185 Again,
186
187 #[error("cache error: {0}")]
188 CacheError(crate::cache::Error),
189
190 #[error("Timed out waiting for first byte of response: {0}")]
191 FirstByteTimeout(tokio::time::error::Elapsed),
192
193 #[error("Timed out waiting for an internal byte of response")]
194 BetweenBytesTimeout,
195}
196
197impl Error {
198 pub fn as_status_code(&self) -> StatusCode {
200 match self {
201 Self::FirstByteTimeout(_) | Self::BetweenBytesTimeout => StatusCode::GATEWAY_TIMEOUT,
202 Self::HyperError(e) => {
203 if e.is_timeout() {
204 StatusCode::GATEWAY_TIMEOUT
205 } else {
206 StatusCode::BAD_GATEWAY
207 }
208 }
209
210 Self::BackendUrl(..)
211 | Self::BackendConnectionError { .. }
212 | Self::InvalidArgument
213 | Self::InvalidHeaderName(..)
214 | Self::InvalidHeaderValue(..)
215 | Self::InvalidMethod(..)
216 | Self::InvalidStatusCode(..)
217 | Self::InvalidUri(..)
218 | Self::IoError(..)
219 | Self::MissingDownstreamMetadata
220 | Self::StreamingChunkSend
221 | Self::UnknownBackend(..)
222 | Self::BadCerts(..)
223 | Self::TlsNoCAAvailable
224 | Self::TlsNoValidCACerts
225 | Self::TlsInvalidHost
226 | Self::TlsCertificateValidationFailed
227 | Self::HttpError(..)
228 | Self::UnfinishedStreamingBody
229 | Self::InvalidClientCert(..)
230 | Self::InvalidAlpnResponse(..)
231 | Self::CacheError(..) => StatusCode::BAD_GATEWAY,
232
233 _ => StatusCode::INTERNAL_SERVER_ERROR,
234 }
235 }
236
237 pub fn to_fastly_status(&self) -> FastlyStatus {
244 match self {
245 Error::BufferLengthError { .. } => FastlyStatus::Buflen,
246 Error::InvalidArgument | Error::HealthcheckCreationError(_) => FastlyStatus::Inval,
247 Error::ValueAbsent => FastlyStatus::None,
248 Error::Unsupported { .. } | Error::NotAvailable(_) => FastlyStatus::Unsupported,
249 Error::HandleError { .. } => FastlyStatus::Badf,
250 Error::InvalidStatusCode { .. } => FastlyStatus::Inval,
251 Error::UnknownBackend(_) | Error::InvalidClientCert(_) => FastlyStatus::Inval,
252 Error::HyperError(e) if e.is_parse() => FastlyStatus::Httpinvalid,
254 Error::HyperError(e) if e.is_user() => FastlyStatus::Httpuser,
255 Error::HyperError(e) if e.is_incomplete_message() => FastlyStatus::Httpincomplete,
256 Error::HyperError(e)
257 if e.source()
258 .and_then(|e| e.downcast_ref::<io::Error>())
259 .map(|ioe| ioe.kind())
260 == Some(io::ErrorKind::UnexpectedEof) =>
261 {
262 FastlyStatus::Httpincomplete
263 }
264 Error::HyperError(_) => FastlyStatus::Error,
265 Error::BackendConnectionError { source, .. } if source.is_parse() => {
267 FastlyStatus::Httpinvalid
268 }
269 Error::BackendConnectionError { source, .. } if source.is_user() => {
270 FastlyStatus::Httpuser
271 }
272 Error::BackendConnectionError { source, .. } if source.is_incomplete_message() => {
273 FastlyStatus::Httpincomplete
274 }
275 Error::BackendConnectionError { source, .. }
276 if source
277 .source()
278 .and_then(|e| e.downcast_ref::<io::Error>())
279 .map(|ioe| ioe.kind())
280 == Some(io::ErrorKind::UnexpectedEof) =>
281 {
282 FastlyStatus::Httpincomplete
283 }
284 Error::BackendConnectionError { .. } => FastlyStatus::Error,
285 Error::GuestError(e) => Self::guest_error_fastly_status(e),
287 Error::DictionaryError(e) => e.to_fastly_status(),
289 Error::DeviceDetectionError(e) => e.to_fastly_status(),
290 Error::ObjectStoreError(e) => e.into(),
291 Error::KvStoreError(e) => e.into(),
292 Error::SecretStoreError(e) => e.into(),
293 Error::Again => FastlyStatus::Again,
294 Error::LimitExceeded { .. } => FastlyStatus::Limitexceeded,
295 Error::CacheError(e) => e.into(),
296 Error::AbiVersionMismatch
298 | Error::BackendUrl(_)
299 | Error::BadCerts(_)
300 | Error::TlsNoCAAvailable
301 | Error::TlsNoValidCACerts
302 | Error::TlsInvalidHost
303 | Error::TlsCertificateValidationFailed
304 | Error::DownstreamRequestError(_)
305 | Error::DownstreamRespSending
306 | Error::FastlyConfig(_)
307 | Error::FatalError(_)
308 | Error::FileFormat
309 | Error::Infallible(_)
310 | Error::InvalidHeaderName(_)
311 | Error::InvalidHeaderValue(_)
312 | Error::InvalidMethod(_)
313 | Error::InvalidUri(_)
314 | Error::IoError(_)
315 | Error::MissingDownstreamMetadata
316 | Error::Other(_)
317 | Error::ProfilingStrategy
318 | Error::StreamingChunkSend
319 | Error::Utf8Expected(_)
320 | Error::BackendNameRegistryError(_)
321 | Error::HttpError(_)
322 | Error::UnknownObjectStore(_)
323 | Error::ObjectStoreKeyValidationError(_)
324 | Error::UnfinishedStreamingBody
325 | Error::SharedMemory
326 | Error::ToStr(_)
327 | Error::FirstByteTimeout(_)
328 | Error::BetweenBytesTimeout
329 | Error::InvalidAlpnResponse(_, _) => FastlyStatus::Error,
330 }
331 }
332
333 fn guest_error_fastly_status(e: &GuestError) -> FastlyStatus {
334 use GuestError::*;
335 match e {
336 PtrNotAligned { .. } => FastlyStatus::Badalign,
337 InvalidFlagValue { .. }
340 | InvalidEnumValue { .. }
341 | PtrOutOfBounds { .. }
342 | PtrOverflow
343 | InvalidUtf8 { .. }
344 | TryFromIntError { .. } => FastlyStatus::Inval,
345 SliceLengthsDiffer => FastlyStatus::Error,
348 InFunc { err, .. } => Self::guest_error_fastly_status(err),
351 }
352 }
353}
354
355#[derive(Debug, thiserror::Error)]
357pub enum HandleError {
358 #[error("Invalid request handle: {0}")]
360 InvalidRequestHandle(crate::wiggle_abi::types::RequestHandle),
361
362 #[error("Invalid response handle: {0}")]
364 InvalidResponseHandle(crate::wiggle_abi::types::ResponseHandle),
365
366 #[error("Invalid body handle: {0}")]
368 InvalidBodyHandle(crate::wiggle_abi::types::BodyHandle),
369
370 #[error("Invalid endpoint handle: {0}")]
372 InvalidEndpointHandle(crate::wiggle_abi::types::EndpointHandle),
373
374 #[error("Invalid pending request promise handle: {0}")]
376 InvalidPendingRequestHandle(crate::wiggle_abi::types::PendingRequestHandle),
377
378 #[error("Invalid pending downstream request handle: {0}")]
380 InvalidPendingDownstreamHandle(crate::wiggle_abi::types::AsyncItemHandle),
381
382 #[error("Invalid pending KV lookup handle: {0}")]
384 InvalidPendingKvLookupHandle(crate::wiggle_abi::types::PendingKvLookupHandle),
385
386 #[error("Invalid pending KV insert handle: {0}")]
388 InvalidPendingKvInsertHandle(crate::wiggle_abi::types::PendingKvInsertHandle),
389
390 #[error("Invalid pending KV delete handle: {0}")]
392 InvalidPendingKvDeleteHandle(crate::wiggle_abi::types::PendingKvDeleteHandle),
393
394 #[error("Invalid pending KV list handle: {0}")]
396 InvalidPendingKvListHandle(crate::wiggle_abi::types::PendingKvListHandle),
397
398 #[error("Invalid dictionary handle: {0}")]
400 InvalidDictionaryHandle(crate::wiggle_abi::types::DictionaryHandle),
401
402 #[error("Invalid object-store handle: {0}")]
404 InvalidObjectStoreHandle(crate::wiggle_abi::types::ObjectStoreHandle),
405
406 #[error("Invalid secret store handle: {0}")]
408 InvalidSecretStoreHandle(crate::wiggle_abi::types::SecretStoreHandle),
409
410 #[error("Invalid secret handle: {0}")]
412 InvalidSecretHandle(crate::wiggle_abi::types::SecretHandle),
413
414 #[error("Invalid async item handle: {0}")]
416 InvalidAsyncItemHandle(crate::wiggle_abi::types::AsyncItemHandle),
417
418 #[error("Invalid acl handle: {0}")]
420 InvalidAclHandle(crate::wiggle_abi::types::AclHandle),
421
422 #[error("Invalid cache handle: {0}")]
424 InvalidCacheHandle(crate::wiggle_abi::types::CacheHandle),
425}
426
427#[derive(Debug, thiserror::Error)]
435pub(crate) enum ExecutionError {
436 #[error("WebAssembly execution trapped: {0}")]
442 WasmTrap(anyhow::Error),
443
444 #[error("Error creating context: {0}")]
446 Context(anyhow::Error),
447
448 #[error("Error type-checking WebAssembly instantiation: {0}")]
450 Typechecking(anyhow::Error),
451
452 #[error("Error instantiating WebAssembly: {0}")]
454 Instantiation(anyhow::Error),
455}
456
457#[derive(Debug, thiserror::Error)]
459pub enum FastlyConfigError {
460 #[error("error reading '{path}': {err}")]
462 IoError {
463 path: String,
464 #[source]
465 err: std::io::Error,
466 },
467
468 #[error("invalid configuration for '{name}': {err}")]
469 InvalidDeviceDetectionDefinition {
470 name: String,
471 #[source]
472 err: DeviceDetectionConfigError,
473 },
474
475 #[error("invalid configuration for '{name}': {err}")]
476 InvalidGeolocationDefinition {
477 name: String,
478 #[source]
479 err: GeolocationConfigError,
480 },
481
482 #[error("invalid configuration for '{name}': {err}")]
483 InvalidAclDefinition {
484 name: String,
485 #[source]
486 err: AclConfigError,
487 },
488
489 #[error("invalid configuration for '{name}': {err}")]
490 InvalidBackendDefinition {
491 name: String,
492 #[source]
493 err: BackendConfigError,
494 },
495
496 #[error("invalid configuration for '{name}': {err}")]
497 InvalidDictionaryDefinition {
498 name: String,
499 #[source]
500 err: DictionaryConfigError,
501 },
502
503 #[error("invalid configuration for '{name}': {err}")]
504 InvalidObjectStoreDefinition {
505 name: String,
506 #[source]
507 err: ObjectStoreConfigError,
508 },
509
510 #[error("invalid configuration for '{name}': {err}")]
511 InvalidSecretStoreDefinition {
512 name: String,
513 #[source]
514 err: SecretStoreConfigError,
515 },
516
517 #[error("invalid configuration for '{name}': {err}")]
518 InvalidShieldingSiteDefinition {
519 name: String,
520 #[source]
521 err: ShieldingSiteConfigError,
522 },
523
524 #[error("error parsing `fastly.toml`: {0}")]
528 InvalidFastlyToml(#[from] toml::de::Error),
529
530 #[error("unsupported manifest version {0}; max supported version is {1}")]
533 UnsupportedManifestVersion(u32, u32),
534}
535
536#[derive(Debug, thiserror::Error)]
538pub enum AclConfigError {
539 #[error(transparent)]
541 IoError(std::io::Error),
542
543 #[error(transparent)]
545 JsonError(serde_json::error::Error),
546
547 #[error("acl must be a TOML table or string")]
548 InvalidType,
549
550 #[error("missing 'file' field")]
551 MissingFile,
552}
553
554#[derive(Debug, thiserror::Error)]
556pub enum BackendConfigError {
557 #[error("definition was not provided as a TOML table")]
558 InvalidEntryType,
559
560 #[error("invalid override_host: {0}")]
561 InvalidOverrideHost(#[from] http::header::InvalidHeaderValue),
562
563 #[error("'override_host' field is empty")]
564 EmptyOverrideHost,
565
566 #[error("'override_host' field was not a string")]
567 InvalidOverrideHostEntry,
568
569 #[error("'cert_host' field is empty")]
570 EmptyCertHost,
571
572 #[error("'cert_host' field was not a string")]
573 InvalidCertHostEntry,
574
575 #[error("'ca_certificate' field is empty")]
576 EmptyCACert,
577
578 #[error("'ca_certificate' field was invalid: {0}")]
579 InvalidCACertEntry(String),
580
581 #[error("'use_sni' field was not a boolean")]
582 InvalidUseSniEntry,
583
584 #[error("'grpc' field was not a boolean")]
585 InvalidGrpcEntry,
586
587 #[error(
588 "'health' field has invalid value '{0}' (expected 'unknown', 'healthy', or 'unhealthy')"
589 )]
590 InvalidHealthEntry(String),
591
592 #[error("invalid url: {0}")]
593 InvalidUrl(#[from] http::uri::InvalidUri),
594
595 #[error("'url' field was not a string")]
596 InvalidUrlEntry,
597
598 #[error("no default definition provided")]
599 MissingDefault,
600
601 #[error("missing 'url' field")]
602 MissingUrl,
603
604 #[error("unrecognized key '{0}'")]
605 UnrecognizedKey(String),
606
607 #[error(transparent)]
608 ClientCertError(#[from] crate::config::ClientCertError),
609
610 #[error("Illegal timeout value (must be an integer >= 0)")]
611 InvalidTimeoutValue,
612}
613
614#[derive(Debug, thiserror::Error)]
616pub enum DictionaryConfigError {
617 #[error(transparent)]
619 IoError(std::io::Error),
620
621 #[error("'contents' was not provided as a TOML table")]
622 InvalidContentsType,
623
624 #[error("inline dictionary value was not a string")]
625 InvalidInlineEntryType,
626
627 #[error("definition was not provided as a TOML table")]
628 InvalidEntryType,
629
630 #[error("'name' field was not a string")]
631 InvalidNameEntry,
632
633 #[error(
634 "'{0}' is not a valid format for the dictionary. Supported format(s) are: 'inline-toml', 'json'."
635 )]
636 InvalidDictionaryFormat(String),
637
638 #[error("'file' field is empty")]
639 EmptyFileEntry,
640
641 #[error("'format' field is empty")]
642 EmptyFormatEntry,
643
644 #[error("'file' field was not a string")]
645 InvalidFileEntry,
646
647 #[error("'format' field was not a string")]
648 InvalidFormatEntry,
649
650 #[error("missing 'contents' field")]
651 MissingContents,
652
653 #[error("no default definition provided")]
654 MissingDefault,
655
656 #[error("missing 'name' field")]
657 MissingName,
658
659 #[error("missing 'file' field")]
660 MissingFile,
661
662 #[error("missing 'format' field")]
663 MissingFormat,
664
665 #[error("unrecognized key '{0}'")]
666 UnrecognizedKey(String),
667
668 #[error("Item key named '{key}' is too long, max size is {size}")]
669 DictionaryItemKeyTooLong { key: String, size: i32 },
670
671 #[error("too many items, max amount is {size}")]
672 DictionaryCountTooLong { size: i32 },
673
674 #[error(
675 "Item value under key named '{key}' is of the wrong format. The value is expected to be a JSON String"
676 )]
677 DictionaryItemValueWrongFormat { key: String },
678
679 #[error("Item value named '{key}' is too long, max size is {size}")]
680 DictionaryItemValueTooLong { key: String, size: i32 },
681
682 #[error(
683 "The file is of the wrong format. The file is expected to contain a single JSON Object"
684 )]
685 DictionaryFileWrongFormat,
686}
687
688#[derive(Debug, thiserror::Error)]
690pub enum DeviceDetectionConfigError {
691 #[error(transparent)]
693 IoError(std::io::Error),
694
695 #[error("definition was not provided as a TOML table")]
696 InvalidEntryType,
697
698 #[error("missing 'file' field")]
699 MissingFile,
700
701 #[error("'file' field is empty")]
702 EmptyFileEntry,
703
704 #[error("missing 'user_agents' field")]
705 MissingUserAgents,
706
707 #[error("inline device detection value was not a string")]
708 InvalidInlineEntryType,
709
710 #[error("'file' field was not a string")]
711 InvalidFileEntry,
712
713 #[error("'user_agents' was not provided as a TOML table")]
714 InvalidUserAgentsType,
715
716 #[error("unrecognized key '{0}'")]
717 UnrecognizedKey(String),
718
719 #[error("missing 'format' field")]
720 MissingFormat,
721
722 #[error("'format' field was not a string")]
723 InvalidFormatEntry,
724
725 #[error(
726 "'{0}' is not a valid format for the device detection mapping. Supported format(s) are: 'inline-toml', 'json'."
727 )]
728 InvalidDeviceDetectionMappingFormat(String),
729
730 #[error(
731 "The file is of the wrong format. The file is expected to contain a single JSON Object"
732 )]
733 DeviceDetectionFileWrongFormat,
734
735 #[error("'format' field is empty")]
736 EmptyFormatEntry,
737
738 #[error(
739 "Item value under key named '{key}' is of the wrong format. The value is expected to be a JSON String"
740 )]
741 DeviceDetectionItemValueWrongFormat { key: String },
742}
743
744#[derive(Debug, thiserror::Error)]
746pub enum GeolocationConfigError {
747 #[error(transparent)]
749 IoError(std::io::Error),
750
751 #[error("definition was not provided as a TOML table")]
752 InvalidEntryType,
753
754 #[error("missing 'file' field")]
755 MissingFile,
756
757 #[error("'file' field is empty")]
758 EmptyFileEntry,
759
760 #[error("missing 'addresses' field")]
761 MissingAddresses,
762
763 #[error("inline geolocation value was not a string")]
764 InvalidInlineEntryType,
765
766 #[error("'file' field was not a string")]
767 InvalidFileEntry,
768
769 #[error("'addresses' was not provided as a TOML table")]
770 InvalidAddressesType,
771
772 #[error("unrecognized key '{0}'")]
773 UnrecognizedKey(String),
774
775 #[error("missing 'format' field")]
776 MissingFormat,
777
778 #[error("'format' field was not a string")]
779 InvalidFormatEntry,
780
781 #[error("IP address not valid: '{0}'")]
782 InvalidAddressEntry(String),
783
784 #[error(
785 "'{0}' is not a valid format for the geolocation mapping. Supported format(s) are: 'inline-toml', 'json'."
786 )]
787 InvalidGeolocationMappingFormat(String),
788
789 #[error(
790 "The file is of the wrong format. The file is expected to contain a single JSON Object"
791 )]
792 GeolocationFileWrongFormat,
793
794 #[error("'format' field is empty")]
795 EmptyFormatEntry,
796
797 #[error(
798 "Item value under key named '{key}' is of the wrong format. The value is expected to be a JSON String"
799 )]
800 GeolocationItemValueWrongFormat { key: String },
801}
802
803#[derive(Debug, thiserror::Error)]
805pub enum ObjectStoreConfigError {
806 #[error(transparent)]
808 IoError(std::io::Error),
809 #[error("The `file` and `data` keys for the object `{0}` are set. Only one can be used.")]
810 FileAndData(String),
811 #[error("The `file` or `data` key for the object `{0}` is not set. One must be used.")]
812 NoFileOrData(String),
813 #[error("The `data` value for the object `{0}` is not a string.")]
814 DataNotAString(String),
815 #[error("The `metadata` value for the object `{0}` is not a string.")]
816 MetadataNotAString(String),
817 #[error("The `file` value for the object `{0}` is not a string.")]
818 FileNotAString(String),
819 #[error("The `key` key for an object is not set. It must be used.")]
820 NoKey,
821 #[error("The `key` value for an object is not a string.")]
822 KeyNotAString,
823 #[error("There is no array of objects for the given store.")]
824 NotAnArray,
825 #[error("There is an object in the given store that is not a table of keys.")]
826 NotATable,
827 #[error("There was an error when manipulating the ObjectStore: {0}.")]
828 ObjectStoreError(#[from] crate::object_store::ObjectStoreError),
829 #[error("There was an error when manipulating the KvStore: {0}.")]
830 KvStoreError(#[from] crate::object_store::KvStoreError),
831 #[error("Invalid `key` value used: {0}.")]
832 KeyValidationError(#[from] crate::object_store::KeyValidationError),
833 #[error("'{0}' is not a valid format for the config store. Supported format(s) are: 'json'.")]
834 InvalidFileFormat(String),
835 #[error("When using a top-level 'file' to load data, both 'file' and 'format' must be set.")]
836 OnlyOneFormatOrFileSet,
837 #[error(
838 "The file is of the wrong format. The file is expected to contain a single JSON Object."
839 )]
840 FileWrongFormat,
841 #[error(
842 "Item value under key named '{key}' is of the wrong format. The value is expected to be a JSON String."
843 )]
844 FileValueWrongFormat { key: String },
845 #[error(
846 "Item value under key named '{key}' is of the wrong format. 'data' and 'file' are mutually exclusive."
847 )]
848 BothDataAndFilePresent { key: String },
849 #[error(
850 "Item value under key named '{key}' is of the wrong format. One of 'data' or 'file' must be present."
851 )]
852 MissingDataOrFile { key: String },
853}
854
855#[derive(Debug, thiserror::Error)]
857pub enum SecretStoreConfigError {
858 #[error(transparent)]
860 IoError(std::io::Error),
861
862 #[error("'{0}' is not a valid format for the secret store. Supported format(s) are: 'json'.")]
863 InvalidFileFormat(String),
864 #[error("When using a top-level 'file' to load data, both 'file' and 'format' must be set.")]
865 OnlyOneFormatOrFileSet,
866 #[error(
867 "The file is of the wrong format. The file is expected to contain a single JSON object."
868 )]
869 FileWrongFormat,
870 #[error(
871 "More than one of `file`, `data`, or `env` keys for the object `{0}` are set. Only one can be used."
872 )]
873 FileDataEnvExclusive(String),
874 #[error("None of `file`, `data`, or `env` keys for the object `{0}` is set. One must be used.")]
875 FileDataEnvNotSet(String),
876 #[error("The `data` value for the object `{0}` is not a string.")]
877 DataNotAString(String),
878 #[error("The `file` value for the object `{0}` is not a string.")]
879 FileNotAString(String),
880 #[error("The `env` value for the object `{0}` is not a string.")]
881 EnvNotAString(String),
882
883 #[error("The `key` key for an object is not set. It must be used.")]
884 NoKey,
885 #[error("The `key` value for an object is not a string.")]
886 KeyNotAString,
887
888 #[error("There is no array of objects for the given store.")]
889 NotAnArray,
890 #[error("There is an object in the given store that is not a table of keys.")]
891 NotATable,
892
893 #[error("Invalid secret store name: {0}")]
894 InvalidSecretStoreName(String),
895
896 #[error("Invalid secret name: {0}")]
897 InvalidSecretName(String),
898}
899
900#[derive(Debug, thiserror::Error)]
902pub enum ShieldingSiteConfigError {
903 #[error(
904 "Illegal TOML value for shielding site; must be either the string 'local' or a table containing an encrypted and unencrypted URL."
905 )]
906 IllegalSiteValue,
907
908 #[error("Illegal TOML string for shielding site; must be 'local'")]
909 IllegalSiteString,
910
911 #[error(
912 "Illegal table for shielding site; must have exactly one key named 'encrypted', and one named 'unencrypted'"
913 )]
914 IllegalSiteDefinition,
915
916 #[error("Illegal URL ({url}): {error}")]
917 IllegalUrl { url: String, error: url::ParseError },
918}
919
920#[derive(Debug, thiserror::Error)]
922pub enum DownstreamRequestError {
923 #[error("Request HOST header is missing or invalid")]
924 InvalidHost,
925
926 #[error("Request URL is invalid")]
927 InvalidUrl,
928}
929
930#[derive(Debug, thiserror::Error)]
933pub enum NonHttpResponse {
934 #[error("graceful Pushpin handoff")]
935 HandoffToPushpin(HandoffInfo),
936 #[error("graceful Backend handoff")]
937 HandoffToBackend(HandoffInfo),
938}