1use serde::{Deserialize, Serialize};
93use smallvec::SmallVec;
94use std::borrow::Cow;
95use std::collections::HashMap;
96use std::io;
97use std::net::SocketAddr;
98use std::time::Duration;
99use thiserror::Error;
100
101#[derive(Debug, Error)]
107pub enum P2PError {
108 #[error("Network error: {0}")]
110 Network(#[from] NetworkError),
111
112 #[error("DHT error: {0}")]
114 Dht(#[from] DhtError),
115
116 #[error("Identity error: {0}")]
118 Identity(#[from] IdentityError),
119
120 #[error("Cryptography error: {0}")]
122 Crypto(#[from] CryptoError),
123
124 #[error("Storage error: {0}")]
126 Storage(#[from] StorageError),
127
128 #[error("Transport error: {0}")]
130 Transport(#[from] TransportError),
131
132 #[error("MCP error: {0}")]
134 Mcp(#[from] McpError),
135
136 #[error("Configuration error: {0}")]
138 Config(#[from] ConfigError),
139
140 #[error("Security error: {0}")]
142 Security(#[from] SecurityError),
143
144 #[error("Bootstrap error: {0}")]
146 Bootstrap(#[from] BootstrapError),
147
148 #[error("IO error: {0}")]
150 Io(#[from] io::Error),
151
152 #[error("Serialization error: {0}")]
154 Serialization(Cow<'static, str>),
155
156 #[error("Validation error: {0}")]
158 Validation(Cow<'static, str>),
159
160 #[error("Operation timed out after {0:?}")]
162 Timeout(Duration),
163
164 #[error("Resource exhausted: {0}")]
166 ResourceExhausted(Cow<'static, str>),
167
168 #[error("Internal error: {0}")]
170 Internal(Cow<'static, str>),
171
172 #[error("Encoding error: {0}")]
174 Encoding(Cow<'static, str>),
175
176 #[error("Record too large: {0} bytes (max 512)")]
178 RecordTooLarge(usize),
179
180 #[error("Time error")]
182 TimeError,
183
184 #[error("Invalid input: {0}")]
186 InvalidInput(String),
187
188 #[error("WebRTC error: {0}")]
190 WebRtcError(String),
191}
192
193#[derive(Debug, Error)]
195pub enum NetworkError {
196 #[error("Connection failed to {addr}: {reason}")]
197 ConnectionFailed {
198 addr: SocketAddr,
199 reason: Cow<'static, str>,
200 },
201
202 #[error("Connection closed unexpectedly")]
203 ConnectionClosed,
204
205 #[error("Invalid network address: {0}")]
206 InvalidAddress(Cow<'static, str>),
207
208 #[error("Peer not found: {0}")]
209 PeerNotFound(Cow<'static, str>),
210
211 #[error("Peer disconnected - peer: {peer}, reason: {reason}")]
212 PeerDisconnected { peer: String, reason: String },
213
214 #[error("Network timeout")]
215 Timeout,
216
217 #[error("Too many connections")]
218 TooManyConnections,
219
220 #[error("Protocol error: {0}")]
221 ProtocolError(Cow<'static, str>),
222
223 #[error("Bind error: {0}")]
224 BindError(Cow<'static, str>),
225}
226
227#[derive(Debug, Error)]
229pub enum DhtError {
230 #[error("Key not found: {0}")]
231 KeyNotFound(Cow<'static, str>),
232
233 #[error("Store operation failed: {0}")]
234 StoreFailed(Cow<'static, str>),
235
236 #[error("Invalid key format: {0}")]
237 InvalidKey(Cow<'static, str>),
238
239 #[error("Routing table full")]
240 RoutingTableFull,
241
242 #[error("No suitable peers found")]
243 NoPeersFound,
244
245 #[error("Replication failed: {0}")]
246 ReplicationFailed(Cow<'static, str>),
247
248 #[error("Query timeout")]
249 QueryTimeout,
250
251 #[error("Routing error: {0}")]
252 RoutingError(Cow<'static, str>),
253
254 #[error("Storage failed: {0}")]
255 StorageFailed(Cow<'static, str>),
256
257 #[error("Insufficient replicas: {0}")]
258 InsufficientReplicas(Cow<'static, str>),
259}
260
261#[derive(Debug, Error)]
263pub enum IdentityError {
264 #[error("Invalid three-word address: {0}")]
265 InvalidThreeWordAddress(Cow<'static, str>),
266
267 #[error("Invalid four-word address: {0}")]
268 InvalidFourWordAddress(Cow<'static, str>),
269
270 #[error("Identity not found: {0}")]
271 IdentityNotFound(Cow<'static, str>),
272
273 #[error("Identity already exists: {0}")]
274 IdentityExists(Cow<'static, str>),
275
276 #[error("Invalid signature")]
277 InvalidSignature,
278
279 #[error("Key derivation failed: {0}")]
280 KeyDerivationFailed(Cow<'static, str>),
281
282 #[error("Permission denied")]
283 PermissionDenied,
284
285 #[error("Invalid peer ID: {0}")]
286 InvalidPeerId(Cow<'static, str>),
287
288 #[error("Invalid format: {0}")]
289 InvalidFormat(Cow<'static, str>),
290
291 #[error("System time error: {0}")]
292 SystemTime(Cow<'static, str>),
293
294
295 #[error("Not found: {0}")]
296 NotFound(Cow<'static, str>),
297
298 #[error("Verification failed: {0}")]
299 VerificationFailed(Cow<'static, str>),
300
301 #[error("Insufficient entropy")]
302 InsufficientEntropy,
303
304 #[error("Access denied: {0}")]
305 AccessDenied(Cow<'static, str>),
306}
307
308#[derive(Debug, Error)]
310pub enum CryptoError {
311 #[error("Encryption failed: {0}")]
312 EncryptionFailed(Cow<'static, str>),
313
314 #[error("Decryption failed: {0}")]
315 DecryptionFailed(Cow<'static, str>),
316
317 #[error("Invalid key length: expected {expected}, got {actual}")]
318 InvalidKeyLength { expected: usize, actual: usize },
319
320 #[error("Signature verification failed")]
321 SignatureVerificationFailed,
322
323 #[error("Key generation failed: {0}")]
324 KeyGenerationFailed(Cow<'static, str>),
325
326 #[error("Invalid public key")]
327 InvalidPublicKey,
328
329 #[error("Invalid private key")]
330 InvalidPrivateKey,
331
332 #[error("HKDF expansion failed: {0}")]
333 HkdfError(Cow<'static, str>),
334}
335
336#[derive(Debug, Error)]
338pub enum StorageError {
339 #[error("Database error: {0}")]
340 Database(Cow<'static, str>),
341
342 #[error("Disk full")]
343 DiskFull,
344
345 #[error("Corrupt data: {0}")]
346 CorruptData(Cow<'static, str>),
347
348 #[error("Storage path not found: {0}")]
349 PathNotFound(Cow<'static, str>),
350
351 #[error("Permission denied: {0}")]
352 PermissionDenied(Cow<'static, str>),
353
354 #[error("Lock acquisition failed")]
355 LockFailed,
356
357 #[error("Lock poisoned: {0}")]
358 LockPoisoned(Cow<'static, str>),
359
360 #[error("File not found: {0}")]
361 FileNotFound(Cow<'static, str>),
362
363 #[error("Corruption detected: {0}")]
364 CorruptionDetected(Cow<'static, str>),
365}
366
367#[derive(Debug, Error)]
369pub enum TransportError {
370 #[error("QUIC error: {0}")]
371 Quic(Cow<'static, str>),
372
373 #[error("TCP error: {0}")]
374 Tcp(Cow<'static, str>),
375
376 #[error("Invalid transport configuration: {0}")]
377 InvalidConfig(Cow<'static, str>),
378
379 #[error("Transport not supported: {0}")]
380 NotSupported(Cow<'static, str>),
381
382 #[error("Stream error: {0}")]
383 StreamError(Cow<'static, str>),
384
385 #[error("Certificate error: {0}")]
386 CertificateError(Cow<'static, str>),
387
388 #[error("Setup failed: {0}")]
389 SetupFailed(Cow<'static, str>),
390
391 #[error("Connection failed to {addr}: {reason}")]
392 ConnectionFailed {
393 addr: SocketAddr,
394 reason: Cow<'static, str>,
395 },
396
397 #[error("Bind error: {0}")]
398 BindError(Cow<'static, str>),
399
400 #[error("Accept failed: {0}")]
401 AcceptFailed(Cow<'static, str>),
402
403 #[error("Not listening")]
404 NotListening,
405
406 #[error("Not initialized")]
407 NotInitialized,
408}
409
410#[derive(Debug, Error)]
412pub enum McpError {
413 #[error("Tool not found: {0}")]
414 ToolNotFound(Cow<'static, str>),
415
416 #[error("Invalid tool configuration: {0}")]
417 InvalidToolConfig(Cow<'static, str>),
418
419 #[error("Execution failed: {0}")]
420 ExecutionFailed(Cow<'static, str>),
421
422 #[error("Permission denied for tool: {0}")]
423 PermissionDenied(Cow<'static, str>),
424
425 #[error("Invalid response format: {0}")]
426 InvalidResponse(Cow<'static, str>),
427
428 #[error("Server unavailable: {0}")]
429 ServerUnavailable(Cow<'static, str>),
430
431 #[error("Invalid request: {0}")]
432 InvalidRequest(Cow<'static, str>),
433
434 #[error("Tool execution failed: {0}")]
435 ToolExecutionFailed(Cow<'static, str>),
436}
437
438#[derive(Debug, Error)]
440pub enum ConfigError {
441 #[error("Missing required field: {0}")]
442 MissingField(Cow<'static, str>),
443
444 #[error("Invalid value for {field}: {reason}")]
445 InvalidValue {
446 field: Cow<'static, str>,
447 reason: Cow<'static, str>,
448 },
449
450 #[error("Configuration file not found: {0}")]
451 FileNotFound(Cow<'static, str>),
452
453 #[error("Parse error: {0}")]
454 ParseError(Cow<'static, str>),
455
456 #[error("Validation failed: {0}")]
457 ValidationFailed(Cow<'static, str>),
458
459 #[error("IO error for {path}: {source}")]
460 IoError {
461 path: Cow<'static, str>,
462 #[source]
463 source: std::io::Error,
464 },
465}
466
467#[derive(Debug, Error)]
469pub enum SecurityError {
470 #[error("Authentication failed")]
471 AuthenticationFailed,
472
473 #[error("Authorization denied")]
474 AuthorizationDenied,
475
476 #[error("Invalid credentials")]
477 InvalidCredentials,
478
479 #[error("Certificate error: {0}")]
480 CertificateError(Cow<'static, str>),
481
482 #[error("Encryption failed: {0}")]
483 EncryptionFailed(Cow<'static, str>),
484
485 #[error("Decryption failed: {0}")]
486 DecryptionFailed(Cow<'static, str>),
487
488 #[error("Invalid key: {0}")]
489 InvalidKey(Cow<'static, str>),
490
491 #[error("Signature verification failed: {0}")]
492 SignatureVerificationFailed(Cow<'static, str>),
493
494 #[error("Key generation failed: {0}")]
495 KeyGenerationFailed(Cow<'static, str>),
496
497 #[error("Authorization failed: {0}")]
498 AuthorizationFailed(Cow<'static, str>),
499}
500
501#[derive(Debug, Error)]
503pub enum BootstrapError {
504 #[error("No bootstrap nodes available")]
505 NoBootstrapNodes,
506
507 #[error("Bootstrap failed: {0}")]
508 BootstrapFailed(Cow<'static, str>),
509
510 #[error("Invalid bootstrap node: {0}")]
511 InvalidBootstrapNode(Cow<'static, str>),
512
513 #[error("Bootstrap timeout")]
514 BootstrapTimeout,
515
516 #[error("Cache error: {0}")]
517 CacheError(Cow<'static, str>),
518
519 #[error("Invalid data: {0}")]
520 InvalidData(Cow<'static, str>),
521}
522
523pub type P2pResult<T> = Result<T, P2PError>;
525
526pub trait Recoverable {
530 fn is_transient(&self) -> bool;
532
533 fn suggested_retry_after(&self) -> Option<Duration>;
535
536 fn max_retries(&self) -> usize;
538}
539
540impl Recoverable for P2PError {
541 fn is_transient(&self) -> bool {
542 match self {
543 P2PError::Network(NetworkError::ConnectionFailed { .. }) => true,
544 P2PError::Network(NetworkError::Timeout) => true,
545 P2PError::Transport(TransportError::ConnectionFailed { .. }) => true,
546 P2PError::Dht(DhtError::QueryTimeout) => true,
547 P2PError::Timeout(_) => true,
548 P2PError::ResourceExhausted(_) => true,
549 P2PError::Io(err) => matches!(
550 err.kind(),
551 io::ErrorKind::WouldBlock | io::ErrorKind::TimedOut | io::ErrorKind::Interrupted
552 ),
553 _ => false,
554 }
555 }
556
557 fn suggested_retry_after(&self) -> Option<Duration> {
558 match self {
559 P2PError::Network(NetworkError::Timeout) => Some(Duration::from_secs(5)),
560 P2PError::Timeout(duration) => Some(*duration * 2),
561 P2PError::ResourceExhausted(_) => Some(Duration::from_secs(30)),
562 P2PError::Transport(TransportError::ConnectionFailed { .. }) => {
563 Some(Duration::from_secs(1))
564 }
565 _ => None,
566 }
567 }
568
569 fn max_retries(&self) -> usize {
570 match self {
571 P2PError::Network(NetworkError::ConnectionFailed { .. }) => 3,
572 P2PError::Transport(TransportError::ConnectionFailed { .. }) => 3,
573 P2PError::Timeout(_) => 2,
574 P2PError::ResourceExhausted(_) => 1,
575 _ => 0,
576 }
577 }
578}
579
580pub trait ErrorContext<T> {
582 fn context(self, msg: &str) -> Result<T, P2PError>;
584
585 fn with_context<F>(self, f: F) -> Result<T, P2PError>
587 where
588 F: FnOnce() -> String;
589}
590
591impl<T, E> ErrorContext<T> for Result<T, E>
592where
593 E: Into<P2PError>,
594{
595 fn context(self, msg: &str) -> Result<T, P2PError> {
596 self.map_err(|e| {
597 let base_error = e.into();
598 P2PError::Internal(format!("{}: {}", msg, base_error).into())
599 })
600 }
601
602 fn with_context<F>(self, f: F) -> Result<T, P2PError>
603 where
604 F: FnOnce() -> String,
605 {
606 self.map_err(|e| {
607 let base_error = e.into();
608 P2PError::Internal(format!("{}: {}", f(), base_error).into())
609 })
610 }
611}
612
613impl P2PError {
615 pub fn connection_failed(addr: SocketAddr, reason: impl Into<String>) -> Self {
617 P2PError::Network(NetworkError::ConnectionFailed {
618 addr,
619 reason: reason.into().into(),
620 })
621 }
622
623 pub fn timeout(duration: Duration) -> Self {
625 P2PError::Timeout(duration)
626 }
627
628 pub fn validation(msg: impl Into<Cow<'static, str>>) -> Self {
630 P2PError::Validation(msg.into())
631 }
632
633 pub fn internal(msg: impl Into<Cow<'static, str>>) -> Self {
635 P2PError::Internal(msg.into())
636 }
637}
638
639impl P2PError {
641 pub fn log(&self) {
643 use log::{error, warn};
644
645 match self {
646 P2PError::Network(NetworkError::Timeout) | P2PError::Timeout(_) => warn!("{}", self),
647
648 P2PError::Validation(_) | P2PError::Config(_) => warn!("{}", self),
649
650 _ => error!("{}", self),
651 }
652 }
653
654 pub fn log_with_context(&self, context: &str) {
656 use log::error;
657 error!("{}: {}", context, self);
658 }
659}
660
661impl From<serde_json::Error> for P2PError {
664 fn from(err: serde_json::Error) -> Self {
665 P2PError::Serialization(err.to_string().into())
666 }
667}
668
669impl From<bincode::Error> for P2PError {
670 fn from(err: bincode::Error) -> Self {
671 P2PError::Serialization(err.to_string().into())
672 }
673}
674
675impl From<std::net::AddrParseError> for P2PError {
676 fn from(err: std::net::AddrParseError) -> Self {
677 P2PError::Network(NetworkError::InvalidAddress(err.to_string().into()))
678 }
679}
680
681impl From<tokio::time::error::Elapsed> for P2PError {
682 fn from(_: tokio::time::error::Elapsed) -> Self {
683 P2PError::Network(NetworkError::Timeout)
684 }
685}
686
687impl From<crate::adaptive::AdaptiveNetworkError> for P2PError {
688 fn from(err: crate::adaptive::AdaptiveNetworkError) -> Self {
689 use crate::adaptive::AdaptiveNetworkError;
690 match err {
691 AdaptiveNetworkError::Network(io_err) => P2PError::Io(io_err),
692 AdaptiveNetworkError::Io(io_err) => P2PError::Io(io_err),
693 AdaptiveNetworkError::Serialization(ser_err) => {
694 P2PError::Serialization(ser_err.to_string().into())
695 }
696 AdaptiveNetworkError::Routing(msg) => {
697 P2PError::Internal(format!("Routing error: {}", msg).into())
698 }
699 AdaptiveNetworkError::Trust(msg) => {
700 P2PError::Internal(format!("Trust error: {}", msg).into())
701 }
702 AdaptiveNetworkError::Learning(msg) => {
703 P2PError::Internal(format!("Learning error: {}", msg).into())
704 }
705 AdaptiveNetworkError::Gossip(msg) => {
706 P2PError::Internal(format!("Gossip error: {}", msg).into())
707 }
708 AdaptiveNetworkError::Other(msg) => P2PError::Internal(msg.into()),
709 }
710 }
711}
712
713#[derive(Debug, Clone, Serialize, Deserialize)]
717pub enum ErrorValue {
718 String(Cow<'static, str>),
719 Number(i64),
720 Bool(bool),
721 Duration(Duration),
722 Address(SocketAddr),
723}
724
725#[derive(Debug, Serialize, Deserialize)]
727pub struct ErrorLog {
728 pub timestamp: i64, pub error_type: &'static str,
730 pub message: Cow<'static, str>,
731 pub context: SmallVec<[(&'static str, ErrorValue); 4]>, pub stack_trace: Option<Cow<'static, str>>,
733}
734
735impl ErrorLog {
736 pub fn from_error(error: &P2PError) -> Self {
738 let mut context = SmallVec::new();
739
740 match error {
742 P2PError::Network(NetworkError::ConnectionFailed { addr, reason }) => {
743 context.push(("address", ErrorValue::Address(*addr)));
744 context.push(("reason", ErrorValue::String(reason.clone())));
745 }
746 P2PError::Timeout(duration) => {
747 context.push(("timeout", ErrorValue::Duration(*duration)));
748 }
749 P2PError::Crypto(CryptoError::InvalidKeyLength { expected, actual }) => {
750 context.push(("expected_length", ErrorValue::Number(*expected as i64)));
751 context.push(("actual_length", ErrorValue::Number(*actual as i64)));
752 }
753 _ => {}
754 }
755
756 ErrorLog {
757 timestamp: chrono::Utc::now().timestamp(),
758 error_type: error_type_name(error),
759 message: error.to_string().into(),
760 context,
761 stack_trace: None,
762 }
763 }
764
765 pub fn with_context(mut self, key: &'static str, value: ErrorValue) -> Self {
766 self.context.push((key, value));
767 self
768 }
769
770 pub fn log(&self) {
771 use log::{error, warn};
772
773 let json = serde_json::to_string(self).unwrap_or_else(|_| self.message.to_string());
774
775 match self.error_type {
776 "Validation" | "Config" => warn!("{}", json),
777 _ => error!("{}", json),
778 }
779 }
780}
781
782fn error_type_name(error: &P2PError) -> &'static str {
783 match error {
784 P2PError::Network(_) => "Network",
785 P2PError::Dht(_) => "DHT",
786 P2PError::Identity(_) => "Identity",
787 P2PError::Crypto(_) => "Crypto",
788 P2PError::Storage(_) => "Storage",
789 P2PError::Transport(_) => "Transport",
790 P2PError::Mcp(_) => "MCP",
791 P2PError::Config(_) => "Config",
792 P2PError::Io(_) => "IO",
793 P2PError::Serialization(_) => "Serialization",
794 P2PError::Validation(_) => "Validation",
795 P2PError::Timeout(_) => "Timeout",
796 P2PError::ResourceExhausted(_) => "ResourceExhausted",
797 P2PError::Internal(_) => "Internal",
798 P2PError::Security(_) => "Security",
799 P2PError::Bootstrap(_) => "Bootstrap",
800 P2PError::Encoding(_) => "Encoding",
801 P2PError::RecordTooLarge(_) => "RecordTooLarge",
802 P2PError::TimeError => "TimeError",
803 P2PError::InvalidInput(_) => "InvalidInput",
804 P2PError::WebRtcError(_) => "WebRTC",
805 }
806}
807
808pub trait ErrorReporting {
810 fn report(&self) -> ErrorLog;
811 fn report_with_context(&self, context: HashMap<String, serde_json::Value>) -> ErrorLog;
812}
813
814impl ErrorReporting for P2PError {
815 fn report(&self) -> ErrorLog {
816 ErrorLog::from_error(self)
817 }
818
819 fn report_with_context(&self, context: HashMap<String, serde_json::Value>) -> ErrorLog {
820 let log = ErrorLog::from_error(self);
821 for (_key, _value) in context {
823 }
827 log
828 }
829}
830
831pub trait IntoAnyhow<T> {
835 fn into_anyhow(self) -> anyhow::Result<T>;
836}
837
838impl<T> IntoAnyhow<T> for P2pResult<T> {
839 fn into_anyhow(self) -> anyhow::Result<T> {
840 self.map_err(|e| anyhow::anyhow!(e))
841 }
842}
843
844pub trait FromAnyhowExt<T> {
845 fn into_p2p_result(self) -> P2pResult<T>;
846}
847
848impl<T> FromAnyhowExt<T> for anyhow::Result<T> {
849 fn into_p2p_result(self) -> P2pResult<T> {
850 self.map_err(|e| P2PError::Internal(e.to_string().into()))
851 }
852}
853
854pub use anyhow::{Context as AnyhowContext, Result as AnyhowResult};
856
857#[cfg(test)]
858mod tests {
859 use super::*;
860
861 #[test]
862 fn test_error_display() {
863 let err =
864 P2PError::connection_failed("127.0.0.1:8080".parse().unwrap(), "Connection refused");
865 assert_eq!(
866 err.to_string(),
867 "Network error: Connection failed to 127.0.0.1:8080: Connection refused"
868 );
869 }
870
871 #[test]
872 fn test_error_context() {
873 let result: Result<(), io::Error> =
874 Err(io::Error::new(io::ErrorKind::NotFound, "file not found"));
875
876 let with_context = crate::error::ErrorContext::context(result, "Failed to load config");
877 assert!(with_context.is_err());
878 assert!(
879 with_context
880 .unwrap_err()
881 .to_string()
882 .contains("Failed to load config")
883 );
884 }
885
886 #[test]
887 fn test_timeout_error() {
888 let err = P2PError::timeout(Duration::from_secs(30));
889 assert_eq!(err.to_string(), "Operation timed out after 30s");
890 }
891
892 #[test]
893 fn test_crypto_error() {
894 let err = P2PError::Crypto(CryptoError::InvalidKeyLength {
895 expected: 32,
896 actual: 16,
897 });
898 assert_eq!(
899 err.to_string(),
900 "Cryptography error: Invalid key length: expected 32, got 16"
901 );
902 }
903
904 #[test]
905 fn test_error_log_serialization() {
906 let error = P2PError::Network(NetworkError::ConnectionFailed {
907 addr: "127.0.0.1:8080".parse().unwrap(),
908 reason: "Connection refused".into(),
909 });
910
911 let log = error
912 .report()
913 .with_context("peer_id", ErrorValue::String("peer123".into()))
914 .with_context("retry_count", ErrorValue::Number(3));
915
916 let json = serde_json::to_string_pretty(&log).unwrap();
917 assert!(json.contains("Network"));
918 assert!(json.contains("127.0.0.1:8080"));
919 assert!(json.contains("peer123"));
920 }
921
922 #[test]
923 fn test_anyhow_conversion() {
924 let p2p_result: P2pResult<()> = Err(P2PError::validation("Invalid input"));
925 let anyhow_result = p2p_result.into_anyhow();
926 assert!(anyhow_result.is_err());
927
928 let anyhow_err = anyhow::anyhow!("Test error");
929 let anyhow_result: anyhow::Result<()> = Err(anyhow_err);
930 let p2p_result = crate::error::FromAnyhowExt::into_p2p_result(anyhow_result);
931 assert!(p2p_result.is_err());
932 match p2p_result.unwrap_err() {
933 P2PError::Internal(msg) => assert!(msg.contains("Test error")),
934 _ => panic!("Expected Internal error"),
935 }
936 }
937}