From 923e6d91b38275ff60ec880c9bb2c1a7e1ad7d19 Mon Sep 17 00:00:00 2001 From: Stephen Toub Date: Thu, 27 Apr 2023 15:31:52 -0400 Subject: [PATCH] Make Exception base class non-generic and clean up derived types (#701) ### Motivation and Context Fixes https://github.com/microsoft/semantic-kernel/issues/573 ### Description - Make the base class non-generic and rename it to SKException - Remove unnecessary private ctors from derived types - Clean up how messages are generated --- .../CustomClient/OpenAIClientBase.cs | 2 +- .../Diagnostics/QdrantMemoryException.cs | 119 ++++++++------ .../QdrantMemoryStore.cs | 15 +- .../QdrantVectorRecord.cs | 2 +- .../AI/AIException.cs | 153 ++++++++++-------- .../Diagnostics/Exception.cs | 64 -------- .../Diagnostics/SKException.cs | 35 ++++ .../Diagnostics/ValidationException.cs | 103 ++++++------ .../KernelException.cs | 107 ++++++------ .../Memory/MemoryException.cs | 102 ++++++------ .../Planning/PlanningException.cs | 107 ++++++------ .../Memory/Collections/MinHeapTests.cs | 4 +- .../TemplateEngine/TemplateException.cs | 107 ++++++------ 13 files changed, 489 insertions(+), 431 deletions(-) delete mode 100644 dotnet/src/SemanticKernel.Abstractions/Diagnostics/Exception.cs create mode 100644 dotnet/src/SemanticKernel.Abstractions/Diagnostics/SKException.cs diff --git a/dotnet/src/Connectors/Connectors.AI.OpenAI/CustomClient/OpenAIClientBase.cs b/dotnet/src/Connectors/Connectors.AI.OpenAI/CustomClient/OpenAIClientBase.cs index 2cd309d0c817..756dd29e2013 100644 --- a/dotnet/src/Connectors/Connectors.AI.OpenAI/CustomClient/OpenAIClientBase.cs +++ b/dotnet/src/Connectors/Connectors.AI.OpenAI/CustomClient/OpenAIClientBase.cs @@ -200,7 +200,7 @@ private async Task ExecutePostRequestAsync(string url, string requestBody, if (response == null) { - throw new AIException(AIException.ErrorCodes.NoResponse, "Empty response"); + throw new AIException(AIException.ErrorCodes.NoResponse); } this.Log.LogTrace("HTTP response: {0} {1}", (int)response.StatusCode, response.StatusCode.ToString("G")); diff --git a/dotnet/src/Connectors/Connectors.Memory.Qdrant/Diagnostics/QdrantMemoryException.cs b/dotnet/src/Connectors/Connectors.Memory.Qdrant/Diagnostics/QdrantMemoryException.cs index 5d40d9569ba0..ac51c3d4193e 100644 --- a/dotnet/src/Connectors/Connectors.Memory.Qdrant/Diagnostics/QdrantMemoryException.cs +++ b/dotnet/src/Connectors/Connectors.Memory.Qdrant/Diagnostics/QdrantMemoryException.cs @@ -5,11 +5,81 @@ namespace Microsoft.SemanticKernel.Connectors.Memory.Qdrant.Diagnostics; +#pragma warning disable CA1032 // Implement standard exception constructors + /// -/// Custom exceptions for the Qdrant connector. +/// Exception thrown for errors related to the Qdrant connector. /// -public class QdrantMemoryException : Exception +public class QdrantMemoryException : SKException { + /// + /// Initializes a new instance of the class with a provided error code. + /// + /// The error code. + public QdrantMemoryException(ErrorCodes errorCode) + : this(errorCode, message: null, innerException: null) + { + } + + /// + /// Initializes a new instance of the class with a provided error code and message. + /// + /// The error code. + /// The exception message. + public QdrantMemoryException(ErrorCodes errorCode, string? message) + : this(errorCode, message, innerException: null) + { + } + + /// + /// Initializes a new instance of the class with a provided error code and inner exception. + /// + /// The error code. + /// The exception that is the cause of the current exception. + public QdrantMemoryException(ErrorCodes errorCode, Exception? innerException) + : this(errorCode, message: null, innerException) + { + } + + /// + /// Initializes a new instance of the class with a provided error code, message, and inner exception. + /// + /// The error code. + /// A string that describes the error. + /// The exception that is the cause of the current exception. + public QdrantMemoryException(ErrorCodes errorCode, string? message, Exception? innerException) + : base(GetDefaultMessage(errorCode, message, innerException), innerException) + { + this.ErrorCode = errorCode; + } + + /// + /// Gets the error code for this exception. + /// + public ErrorCodes ErrorCode { get; } + + /// Translate the error code into a default message. + private static string GetDefaultMessage(ErrorCodes errorCode, string? message, Exception? innerException) + { + if (message is not null) + { + return message; + } + + string description = errorCode switch + { + ErrorCodes.UnableToDeserializeRecordPayload => "Unable to deserialize record payload", + ErrorCodes.FailedToUpsertVectors => "Failed to upsert vectors", + ErrorCodes.FailedToGetVectorData => "Failed to get vector data", + ErrorCodes.FailedToRemoveVectorData => "Failed to remove vector data", + ErrorCodes.FailedToConvertMemoryRecordToQdrantVectorRecord => "Failed to convert memory record to Qdrant vector record", + ErrorCodes.FailedToConvertQdrantVectorRecordToMemoryRecord => "Failed to convert Qdrant vector record to memory record", + _ => $"Unknown error ({errorCode:G})", + }; + + return innerException is not null ? $"{description}: {innerException.Message}" : description; + } + /// /// Error codes for the Qdrant connector exceptions. /// @@ -18,7 +88,7 @@ public enum ErrorCodes /// /// Unknown error. /// - UnknownError, + UnknownError = -1, /// /// Failed to deserialize the record payload. @@ -50,47 +120,4 @@ public enum ErrorCodes /// FailedToConvertQdrantVectorRecordToMemoryRecord } - - /// - /// Initializes a new instance of the class with error code unknown. - /// - /// The exception message. - public QdrantMemoryException(string message) - : this(ErrorCodes.UnknownError, message) - { - } - - /// - /// Initializes a new instance of the class with a provided error code. - /// - /// The error code. - /// The exception message. - public QdrantMemoryException(ErrorCodes error, string message) - : base(error, message) - { - } - - /// - /// Initializes a new instance of the class with an inner exception. - /// - /// The error code. - /// The exception message. - /// The inner exception - public QdrantMemoryException(ErrorCodes error, string message, Exception innerException) - : base(BuildMessage(error, message), innerException) - { - } - - private QdrantMemoryException() - { - } - - private static string BuildMessage(ErrorCodes error, string? message) - { - return message != null ? $"{error.ToString("G")}: {message}" : error.ToString("G"); - } - - private QdrantMemoryException(string message, System.Exception innerException) : base(message, innerException) - { - } } diff --git a/dotnet/src/Connectors/Connectors.Memory.Qdrant/QdrantMemoryStore.cs b/dotnet/src/Connectors/Connectors.Memory.Qdrant/QdrantMemoryStore.cs index 9ccf313d4b46..200bc1b47610 100644 --- a/dotnet/src/Connectors/Connectors.Memory.Qdrant/QdrantMemoryStore.cs +++ b/dotnet/src/Connectors/Connectors.Memory.Qdrant/QdrantMemoryStore.cs @@ -85,8 +85,7 @@ public async Task UpsertAsync(string collectionName, MemoryRecord record if (vectorData == null) { - throw new QdrantMemoryException(QdrantMemoryException.ErrorCodes.FailedToConvertMemoryRecordToQdrantVectorRecord, - $"Failed to convert MemoryRecord to QdrantVectorRecord"); + throw new QdrantMemoryException(QdrantMemoryException.ErrorCodes.FailedToConvertMemoryRecordToQdrantVectorRecord); } try @@ -100,7 +99,6 @@ public async Task UpsertAsync(string collectionName, MemoryRecord record { throw new QdrantMemoryException( QdrantMemoryException.ErrorCodes.FailedToUpsertVectors, - $"Failed to upsert due to HttpRequestException: {ex.Message}", ex); } @@ -125,7 +123,6 @@ public async Task UpsertAsync(string collectionName, MemoryRecord record { throw new QdrantMemoryException( QdrantMemoryException.ErrorCodes.FailedToUpsertVectors, - $"Failed to upsert due to HttpRequestException: {ex.Message}", ex); } @@ -157,14 +154,12 @@ public async Task UpsertAsync(string collectionName, MemoryRecord record { throw new QdrantMemoryException( QdrantMemoryException.ErrorCodes.FailedToGetVectorData, - $"Failed to get vector data from Qdrant: {ex.Message}", ex); } catch (MemoryException ex) { throw new QdrantMemoryException( QdrantMemoryException.ErrorCodes.FailedToConvertQdrantVectorRecordToMemoryRecord, - $"Failed deserialize Qdrant response to Memory Record: {ex.Message}", ex); } } @@ -216,14 +211,12 @@ public async Task UpsertAsync(string collectionName, MemoryRecord record { throw new QdrantMemoryException( QdrantMemoryException.ErrorCodes.FailedToGetVectorData, - $"Failed to get vector data from Qdrant: {ex.Message}", ex); } catch (MemoryException ex) { throw new QdrantMemoryException( QdrantMemoryException.ErrorCodes.FailedToConvertQdrantVectorRecordToMemoryRecord, - $"Failed deserialize Qdrant response to Memory Record: {ex.Message}", ex); } } @@ -262,7 +255,6 @@ public async Task RemoveAsync(string collectionName, string key, CancellationTok { throw new QdrantMemoryException( QdrantMemoryException.ErrorCodes.FailedToRemoveVectorData, - $"Failed to remove vector data from Qdrant {ex.Message}", ex); } } @@ -291,7 +283,6 @@ public async Task RemoveWithPointIdAsync(string collectionName, string pointId, { throw new QdrantMemoryException( QdrantMemoryException.ErrorCodes.FailedToRemoveVectorData, - $"Failed to remove vector data from Qdrant {ex.Message}", ex); } } @@ -314,7 +305,6 @@ public async Task RemoveWithPointIdBatchAsync(string collectionName, IEnumerable { throw new QdrantMemoryException( QdrantMemoryException.ErrorCodes.FailedToRemoveVectorData, - $"Error in batch removing data from Qdrant {ex.Message}", ex); } } @@ -433,8 +423,7 @@ private async Task ConvertFromMemoryRecordAsync(string colle if (vectorData == null) { - throw new QdrantMemoryException(QdrantMemoryException.ErrorCodes.FailedToConvertMemoryRecordToQdrantVectorRecord, - $"Failed to convert MemoryRecord to QdrantVectorRecord"); + throw new QdrantMemoryException(QdrantMemoryException.ErrorCodes.FailedToConvertMemoryRecordToQdrantVectorRecord); } return vectorData; diff --git a/dotnet/src/Connectors/Connectors.Memory.Qdrant/QdrantVectorRecord.cs b/dotnet/src/Connectors/Connectors.Memory.Qdrant/QdrantVectorRecord.cs index b29992ae94d1..802602409a38 100644 --- a/dotnet/src/Connectors/Connectors.Memory.Qdrant/QdrantVectorRecord.cs +++ b/dotnet/src/Connectors/Connectors.Memory.Qdrant/QdrantVectorRecord.cs @@ -80,7 +80,7 @@ public static QdrantVectorRecord FromJsonMetadata(string pointId, IEnumerable -/// AI logic exception +/// Exception thrown for errors related to AI logic. /// -public class AIException : Exception +public class AIException : SKException { + /// + /// Initializes a new instance of the class with a provided error code. + /// + /// The error code. + public AIException(ErrorCodes errorCode) + : this(errorCode, message: null, detail: null, innerException: null) + { + } + + /// + /// Initializes a new instance of the class with a provided error code and message. + /// + /// The error code. + /// The exception message. + public AIException(ErrorCodes errorCode, string? message) + : this(errorCode, message, detail: null, innerException: null) + { + } + + /// + /// Initializes a new instance of the class with a provided error code, message, and inner exception. + /// + /// The error code. + /// A string that describes the error. + /// The exception that is the cause of the current exception. + public AIException(ErrorCodes errorCode, string? message, Exception? innerException) + : this(errorCode, message, detail: null, innerException) + { + } + + /// + /// Initializes a new instance of the class with a provided error code, message, and inner exception. + /// + /// The error code. + /// A string that describes the error. + /// A string that provides additional details about the error. + public AIException(ErrorCodes errorCode, string? message, string? detail) + : this(errorCode, message, detail: null, innerException: null) + { + } + + /// + /// Initializes a new instance of the class with a provided error code, message, additional details, and inner exception. + /// + /// The error code. + /// A string that describes the error. + /// A string that provides additional details about the error. + /// The exception that is the cause of the current exception. + public AIException(ErrorCodes errorCode, string? message, string? detail, Exception? innerException) + : base(GetDefaultMessage(errorCode, message), innerException) + { + this.ErrorCode = errorCode; + this.Detail = detail; + } + + /// + /// Gets the error code for this exception. + /// + public ErrorCodes ErrorCode { get; } + + /// + /// Gets the extended details for this exception. + /// + public string? Detail { get; } + + /// Translate the error code into a default message. + private static string GetDefaultMessage(ErrorCodes errorCode, string? message) + { + string description = errorCode switch + { + ErrorCodes.NoResponse => "No response", + ErrorCodes.AccessDenied => "Access denied", + ErrorCodes.InvalidRequest => "Invalid request", + ErrorCodes.InvalidResponseContent => "Invalid response content", + ErrorCodes.Throttling => "Throttling", + ErrorCodes.RequestTimeout => "Request timeout", + ErrorCodes.ServiceError => "Service error", + ErrorCodes.ModelNotAvailable => "Model not available", + ErrorCodes.InvalidConfiguration => "Invalid configuration", + ErrorCodes.FunctionTypeNotSupported => "Function type not supported", + _ => $"Unknown error ({errorCode:G})", + }; + + return message is not null ? $"{description}: {message}" : description; + } + /// /// Possible error codes for exceptions /// @@ -70,65 +158,4 @@ public enum ErrorCodes /// FunctionTypeNotSupported, } - - /// - /// The exception's error code. - /// - public ErrorCodes ErrorCode { get; set; } - - /// - /// The exception's detail. - /// - public string? Detail { get; set; } - - /// - /// Construct an exception with an error code and message. - /// - /// Error code of the exception. - /// Message of the exception - public AIException(ErrorCodes errCode, string? message = null) : base(errCode, message) - { - this.ErrorCode = errCode; - } - - /// - /// Construct an exception with an error code, message, and existing exception. - /// - /// Error code of the exception. - /// Message of the exception. - /// An exception that was thrown. - public AIException(ErrorCodes errCode, string message, Exception? e) : base(errCode, message, e) - { - this.ErrorCode = errCode; - } - - /// - /// Construct an exception with an error code, message, and existing exception. - /// - /// Error code of the exception. - /// Message of the exception. - /// More details about the exception - public AIException(ErrorCodes errCode, string message, string? detail) : this(errCode, message) - { - this.Detail = detail; - } - - #region private ================================================================================ - - private AIException() - { - // Not allowed, error code is required - } - - private AIException(string message) : base(message) - { - // Not allowed, error code is required - } - - private AIException(string message, Exception innerException) : base(message, innerException) - { - // Not allowed, error code is required - } - - #endregion } diff --git a/dotnet/src/SemanticKernel.Abstractions/Diagnostics/Exception.cs b/dotnet/src/SemanticKernel.Abstractions/Diagnostics/Exception.cs deleted file mode 100644 index 78f86cad0753..000000000000 --- a/dotnet/src/SemanticKernel.Abstractions/Diagnostics/Exception.cs +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. - -using System; - -namespace Microsoft.SemanticKernel.Diagnostics; - -/// -/// Base exception for all SK exceptions -/// -/// Enum type used for the error codes -public abstract class Exception : Exception where TErrorCode : Enum -{ - /// - /// Initializes a new instance of the class. - /// - /// The error type. - /// The message. - protected Exception(TErrorCode errCode, string? message = null) : base(BuildMessage(errCode, message)) - { - } - - /// - /// Initializes a new instance of the class. - /// - /// The error type. - /// The message. - /// The inner exception. - protected Exception(TErrorCode errCode, string? message, Exception? innerException) - : base(BuildMessage(errCode, message), innerException) - { - } - - /// - /// Parameterless ctor, do not use - /// - protected Exception() - { - // Not allowed, error code is required - } - - /// - /// Standard ctor, do not use - /// - /// Exception message - protected Exception(string message) : base(message) - { - // Not allowed, error code is required - } - - /// - /// Standard ctor, do not use - /// - /// Exception message - /// Internal exception - protected Exception(string message, Exception innerException) : base(message, innerException) - { - // Not allowed, error code is required - } - - private static string BuildMessage(TErrorCode errorType, string? message) - { - return message != null ? $"{errorType.ToString("G")}: {message}" : errorType.ToString("G"); - } -} diff --git a/dotnet/src/SemanticKernel.Abstractions/Diagnostics/SKException.cs b/dotnet/src/SemanticKernel.Abstractions/Diagnostics/SKException.cs new file mode 100644 index 000000000000..bc21d3db998e --- /dev/null +++ b/dotnet/src/SemanticKernel.Abstractions/Diagnostics/SKException.cs @@ -0,0 +1,35 @@ +// Copyright (c) Microsoft. All rights reserved. + +using System; + +namespace Microsoft.SemanticKernel.Diagnostics; + +/// +/// Provides the base exception from which all Semantic Kernel exceptions derive. +/// +public abstract class SKException : Exception +{ + /// + /// Initializes a new instance of the class with a default message. + /// + protected SKException() + { + } + + /// + /// Initializes a new instance of the class with its message set to . + /// + /// A string that describes the error. + protected SKException(string? message) : base(message) + { + } + + /// + /// Initializes a new instance of the class with its message set to . + /// + /// A string that describes the error. + /// The exception that is the cause of the current exception. + protected SKException(string? message, Exception? innerException) : base(message, innerException) + { + } +} diff --git a/dotnet/src/SemanticKernel.Abstractions/Diagnostics/ValidationException.cs b/dotnet/src/SemanticKernel.Abstractions/Diagnostics/ValidationException.cs index c95dfe510c87..333f32cd9168 100644 --- a/dotnet/src/SemanticKernel.Abstractions/Diagnostics/ValidationException.cs +++ b/dotnet/src/SemanticKernel.Abstractions/Diagnostics/ValidationException.cs @@ -4,11 +4,65 @@ namespace Microsoft.SemanticKernel.Diagnostics; +#pragma warning disable CA1032 // Implement standard exception constructors + /// -/// Generic validation exception +/// Exception thrown for errors related to validation. /// -public class ValidationException : Exception +public class ValidationException : SKException { + /// + /// Initializes a new instance of the class with a provided error code. + /// + /// The error code. + public ValidationException(ErrorCodes errorCode) + : this(errorCode, message: null, innerException: null) + { + } + + /// + /// Initializes a new instance of the class with a provided error code and message. + /// + /// The error code. + /// The exception message. + public ValidationException(ErrorCodes errorCode, string? message) + : this(errorCode, message, innerException: null) + { + } + + /// + /// Initializes a new instance of the class with a provided error code, message, and inner exception. + /// + /// The error code. + /// A string that describes the error. + /// The exception that is the cause of the current exception. + public ValidationException(ErrorCodes errorCode, string? message, Exception? innerException) + : base(GetDefaultMessage(errorCode, message), innerException) + { + this.ErrorCode = errorCode; + } + + /// + /// Gets the error code for this exception. + /// + public ErrorCodes ErrorCode { get; } + + /// Translate the error code into a default message. + private static string GetDefaultMessage(ErrorCodes errorCode, string? message) + { + string description = errorCode switch + { + ErrorCodes.NullValue => "Null value", + ErrorCodes.EmptyValue => "Empty value", + ErrorCodes.OutOfRange => "Out of range", + ErrorCodes.MissingPrefix => "Missing prefix", + ErrorCodes.DirectoryNotFound => "Directory not found", + _ => $"Unknown error ({errorCode:G})", + }; + + return message is not null ? $"{description}: {message}" : description; + } + /// /// Error codes for . /// @@ -44,49 +98,4 @@ public enum ErrorCodes /// DirectoryNotFound, } - - /// - /// Gets the error code of the exception. - /// - public ErrorCodes ErrorCode { get; set; } - - /// - /// Initializes a new instance of the class. - /// - /// The error code. - /// The message. - public ValidationException(ErrorCodes errCode, string? message = null) : base(errCode, message) - { - this.ErrorCode = errCode; - } - - /// - /// Initializes a new instance of the class. - /// - /// The error code. - /// The message. - /// The inner exception. - public ValidationException(ErrorCodes errCode, string message, Exception? e) : base(errCode, message, e) - { - this.ErrorCode = errCode; - } - - #region private ================================================================================ - - private ValidationException() - { - // Not allowed, error code is required - } - - private ValidationException(string message) : base(message) - { - // Not allowed, error code is required - } - - private ValidationException(string message, Exception innerException) : base(message, innerException) - { - // Not allowed, error code is required - } - - #endregion } diff --git a/dotnet/src/SemanticKernel.Abstractions/KernelException.cs b/dotnet/src/SemanticKernel.Abstractions/KernelException.cs index ae412392c6cd..8d4750126515 100644 --- a/dotnet/src/SemanticKernel.Abstractions/KernelException.cs +++ b/dotnet/src/SemanticKernel.Abstractions/KernelException.cs @@ -5,11 +5,69 @@ namespace Microsoft.SemanticKernel; +#pragma warning disable CA1032 // Implement standard exception constructors + /// -/// Kernel logic exception +/// Exception thrown for errors related to kernel logic. /// -public class KernelException : Exception +public class KernelException : SKException { + /// + /// Initializes a new instance of the class with a provided error code. + /// + /// The error code. + public KernelException(ErrorCodes errorCode) + : this(errorCode, message: null, innerException: null) + { + } + + /// + /// Initializes a new instance of the class with a provided error code and message. + /// + /// The error code. + /// The exception message. + public KernelException(ErrorCodes errorCode, string? message) + : this(errorCode, message, innerException: null) + { + } + + /// + /// Initializes a new instance of the class with a provided error code, message, and inner exception. + /// + /// The error code. + /// A string that describes the error. + /// The exception that is the cause of the current exception. + public KernelException(ErrorCodes errorCode, string? message, Exception? innerException) + : base(GetDefaultMessage(errorCode, message), innerException) + { + this.ErrorCode = errorCode; + } + + /// + /// Gets the error code for this exception. + /// + public ErrorCodes ErrorCode { get; } + + /// Translate the error code into a default message. + private static string GetDefaultMessage(ErrorCodes errorCode, string? message) + { + string description = errorCode switch + { + ErrorCodes.InvalidFunctionDescription => "Invalid function description", + ErrorCodes.FunctionOverloadNotSupported => "Function overload not supported", + ErrorCodes.FunctionNotAvailable => "Function not available", + ErrorCodes.FunctionTypeNotSupported => "Function type not supported", + ErrorCodes.InvalidFunctionType => "Invalid function type", + ErrorCodes.InvalidServiceConfiguration => "Invalid service configuration", + ErrorCodes.ServiceNotFound => "Service not found", + ErrorCodes.SkillCollectionNotSet => "Skill collection not set", + ErrorCodes.FunctionInvokeError => "Function invoke error", + _ => $"Unknown error ({errorCode:G})", + }; + + return message is not null ? $"{description}: {message}" : description; + } + /// /// Semantic kernel error codes. /// @@ -65,49 +123,4 @@ public enum ErrorCodes /// FunctionInvokeError, } - - /// - /// Error code. - /// - public ErrorCodes ErrorCode { get; set; } - - /// - /// Constructor for KernelException. - /// - /// Error code to put in KernelException. - /// Message to put in KernelException. - public KernelException(ErrorCodes errCode, string? message = null) : base(errCode, message) - { - this.ErrorCode = errCode; - } - - /// - /// Constructor for KernelException. - /// - /// Error code to put in KernelException. - /// Message to put in KernelException. - /// Exception to embed in KernelException. - public KernelException(ErrorCodes errCode, string message, Exception? e) : base(errCode, message, e) - { - this.ErrorCode = errCode; - } - - #region private ================================================================================ - - private KernelException() - { - // Not allowed, error code is required - } - - private KernelException(string message) : base(message) - { - // Not allowed, error code is required - } - - private KernelException(string message, Exception innerException) : base(message, innerException) - { - // Not allowed, error code is required - } - - #endregion } diff --git a/dotnet/src/SemanticKernel.Abstractions/Memory/MemoryException.cs b/dotnet/src/SemanticKernel.Abstractions/Memory/MemoryException.cs index dc0f7a94419b..5717fadf1219 100644 --- a/dotnet/src/SemanticKernel.Abstractions/Memory/MemoryException.cs +++ b/dotnet/src/SemanticKernel.Abstractions/Memory/MemoryException.cs @@ -5,11 +5,64 @@ namespace Microsoft.SemanticKernel.Memory; +#pragma warning disable CA1032 // Implement standard exception constructors + /// -/// Memory logic exception +/// Exception thrown for errors related to memory logic. /// -public class MemoryException : Exception +public class MemoryException : SKException { + /// + /// Initializes a new instance of the class with a provided error code. + /// + /// The error code. + public MemoryException(ErrorCodes error) + : this(error, message: null, innerException: null) + { + } + + /// + /// Initializes a new instance of the class with a provided error code and message. + /// + /// The error code. + /// The exception message. + public MemoryException(ErrorCodes errorCode, string? message) + : this(errorCode, message, innerException: null) + { + } + + /// + /// Initializes a new instance of the class with a provided error code, message, and inner exception. + /// + /// The error code. + /// A string that describes the error. + /// The exception that is the cause of the current exception. + public MemoryException(ErrorCodes errorCode, string? message, Exception? innerException) + : base(GetDefaultMessage(errorCode, message), innerException) + { + this.ErrorCode = errorCode; + } + + /// + /// Gets the error code for this exception. + /// + public ErrorCodes ErrorCode { get; } + + /// Translate the error code into a default message. + private static string GetDefaultMessage(ErrorCodes errorCode, string? message) + { + string description = errorCode switch + { + ErrorCodes.FailedToCreateCollection => "Failed to create collection", + ErrorCodes.FailedToDeleteCollection => "Failed to delete collection", + ErrorCodes.UnableToDeserializeMetadata => "Unable to deserialize metadata", + ErrorCodes.AttemptedToAccessNonexistentCollection => "Attempted to access non-existent collection", + _ => $"Unknown error ({errorCode:G})", + }; + + return message is not null ? $"{description}: {message}" : description; + } + /// /// Semantic kernel memory error codes. /// @@ -40,49 +93,4 @@ public enum ErrorCodes /// AttemptedToAccessNonexistentCollection, } - - /// - /// Error code. - /// - public ErrorCodes ErrorCode { get; set; } - - /// - /// Constructor for MemoryException. - /// - /// Error code to put in MemoryException. - /// Message to put in MemoryException. - public MemoryException(ErrorCodes errCode, string? message = null) : base(errCode, message) - { - this.ErrorCode = errCode; - } - - /// - /// Constructor for MemoryException. - /// - /// Error code to put in MemoryException. - /// Message to put in MemoryException. - /// Exception to embed in MemoryException. - public MemoryException(ErrorCodes errCode, string message, Exception? e) : base(errCode, message, e) - { - this.ErrorCode = errCode; - } - - #region private ================================================================================ - - private MemoryException() - { - // Not allowed, error code is required - } - - private MemoryException(string message) : base(message) - { - // Not allowed, error code is required - } - - private MemoryException(string message, Exception innerException) : base(message, innerException) - { - // Not allowed, error code is required - } - - #endregion } diff --git a/dotnet/src/SemanticKernel.Abstractions/Planning/PlanningException.cs b/dotnet/src/SemanticKernel.Abstractions/Planning/PlanningException.cs index c5d91806b462..5a4bd2d7f829 100644 --- a/dotnet/src/SemanticKernel.Abstractions/Planning/PlanningException.cs +++ b/dotnet/src/SemanticKernel.Abstractions/Planning/PlanningException.cs @@ -5,79 +5,86 @@ namespace Microsoft.SemanticKernel.Planning; +#pragma warning disable CA1032 // Implement standard exception constructors + /// -/// Planning exception. +/// Exception thrown for errors related to planning. /// -public class PlanningException : Exception +public class PlanningException : SKException { /// - /// Error codes for . + /// Initializes a new instance of the class with a provided error code. /// - public enum ErrorCodes + /// The error code. + public PlanningException(ErrorCodes errorCode) + : this(errorCode, message: null, innerException: null) { - /// - /// Unknown error. - /// - UnknownError = -1, - - /// - /// Invalid goal. - /// - InvalidGoal = 0, - - /// - /// Invalid plan. - /// - InvalidPlan = 1, - - /// - /// Invalid configuration. - /// - InvalidConfiguration = 2, } /// - /// Gets the error code of the exception. + /// Initializes a new instance of the class with a provided error code and message. /// - public ErrorCodes ErrorCode { get; } - - /// - /// Initializes a new instance of the class. - /// - /// The error code. - /// The message. - public PlanningException(ErrorCodes errCode, string? message = null) : base(errCode, message) + /// The error code. + /// The exception message. + public PlanningException(ErrorCodes errorCode, string? message) + : this(errorCode, message, innerException: null) { - this.ErrorCode = errCode; } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class with a provided error code, message, and inner exception. /// - /// The error code. - /// The message. - /// The inner exception. - public PlanningException(ErrorCodes errCode, string message, Exception? e) : base(errCode, message, e) + /// The error code. + /// A string that describes the error. + /// The exception that is the cause of the current exception. + public PlanningException(ErrorCodes errorCode, string? message, Exception? innerException) + : base(GetDefaultMessage(errorCode, message), innerException) { - this.ErrorCode = errCode; + this.ErrorCode = errorCode; } - #region private ================================================================================ + /// + /// Gets the error code for this exception. + /// + public ErrorCodes ErrorCode { get; } - private PlanningException() + /// Translate the error code into a default message. + private static string GetDefaultMessage(ErrorCodes errorCode, string? message) { - // Not allowed, error code is required - } + string description = errorCode switch + { + ErrorCodes.InvalidGoal => "Invalid goal", + ErrorCodes.InvalidPlan => "Invalid plan", + ErrorCodes.InvalidConfiguration => "Invalid configuration", + _ => $"Unknown error ({errorCode:G})", + }; - private PlanningException(string message) : base(message) - { - // Not allowed, error code is required + return message is not null ? $"{description}: {message}" : description; } - private PlanningException(string message, Exception innerException) : base(message, innerException) + /// + /// Error codes for . + /// + public enum ErrorCodes { - // Not allowed, error code is required - } + /// + /// Unknown error. + /// + UnknownError = -1, - #endregion + /// + /// Invalid goal. + /// + InvalidGoal, + + /// + /// Invalid plan. + /// + InvalidPlan, + + /// + /// Invalid configuration. + /// + InvalidConfiguration, + } } diff --git a/dotnet/src/SemanticKernel.UnitTests/Memory/Collections/MinHeapTests.cs b/dotnet/src/SemanticKernel.UnitTests/Memory/Collections/MinHeapTests.cs index 5a3fb632c17d..429cb5fe7768 100644 --- a/dotnet/src/SemanticKernel.UnitTests/Memory/Collections/MinHeapTests.cs +++ b/dotnet/src/SemanticKernel.UnitTests/Memory/Collections/MinHeapTests.cs @@ -31,7 +31,7 @@ public void ItThrowsExceptionWhenCapacityIsInvalid() // Assert Assert.Equal(ValidationException.ErrorCodes.OutOfRange, exception.ErrorCode); - Assert.Equal("OutOfRange: MinHeap capacity must be greater than 0.", exception.Message); + Assert.Equal("Out of range: MinHeap capacity must be greater than 0.", exception.Message); } [Fact] @@ -95,7 +95,7 @@ public void ItThrowsExceptionOnAddingItemsAtInvalidIndex() // Assert Assert.Equal(ValidationException.ErrorCodes.OutOfRange, exception.ErrorCode); - Assert.Equal("OutOfRange: startAt value must be less than items count.", exception.Message); + Assert.Equal("Out of range: startAt value must be less than items count.", exception.Message); } [Fact] diff --git a/dotnet/src/SemanticKernel/TemplateEngine/TemplateException.cs b/dotnet/src/SemanticKernel/TemplateEngine/TemplateException.cs index 1bfb33b5ac4c..f75d5db08d66 100644 --- a/dotnet/src/SemanticKernel/TemplateEngine/TemplateException.cs +++ b/dotnet/src/SemanticKernel/TemplateEngine/TemplateException.cs @@ -5,20 +5,73 @@ namespace Microsoft.SemanticKernel.TemplateEngine; +#pragma warning disable CA1032 // Implement standard exception constructors + /// -/// Template exception. +/// Exception thrown for errors related to templating. /// -public class TemplateException : Exception +public class TemplateException : SKException { + /// + /// Initializes a new instance of the class with a provided error code. + /// + /// The error code. + public TemplateException(ErrorCodes error) + : this(error, message: null, innerException: null) + { + } + + /// + /// Initializes a new instance of the class with a provided error code and message. + /// + /// The error code. + /// The exception message. + public TemplateException(ErrorCodes errorCode, string? message) + : this(errorCode, message, innerException: null) + { + } + + /// + /// Initializes a new instance of the class with a provided error code, message, and inner exception. + /// + /// The error code. + /// A string that describes the error. + /// The exception that is the cause of the current exception. + public TemplateException(ErrorCodes errorCode, string? message, Exception? innerException) + : base(GetDefaultMessage(errorCode, message), innerException) + { + this.ErrorCode = errorCode; + } + + /// + /// Gets the error code for this exception. + /// + public ErrorCodes ErrorCode { get; } + + /// Translate the error code into a default message. + private static string GetDefaultMessage(ErrorCodes errorCode, string? message) + { + string description = errorCode switch + { + ErrorCodes.SyntaxError => "Syntax error", + ErrorCodes.UnexpectedBlockType => "Unexpected block type", + ErrorCodes.FunctionNotFound => "Function not found", + ErrorCodes.RuntimeError => "Runtime error", + _ => $"Unknown error ({errorCode:G})", + }; + + return message is not null ? $"{description}: {message}" : description; + } + /// /// Error codes for . /// public enum ErrorCodes { /// - /// Unknown/undefined error type. Don't use this value. + /// Unknown error. /// - Unknown = -1, + UnknownError = -1, /// /// Syntax error, the template syntax used is not valid. @@ -40,50 +93,4 @@ public enum ErrorCodes /// RuntimeError = 3, } - - /// - /// Error code. - /// - public ErrorCodes ErrorCode { get; set; } - - /// - /// Initializes a new instance of the class. - /// - /// The template error type. - /// The exception message. - public TemplateException(ErrorCodes errCode, string? message = null) - : base(errCode, message) - { - this.ErrorCode = errCode; - } - - /// - /// Construct an exception with an error code, message, and existing exception. - /// - /// Error code of the exception. - /// Message of the exception. - /// An exception that was thrown. - public TemplateException(ErrorCodes errCode, string message, Exception? e) : base(errCode, message, e) - { - this.ErrorCode = errCode; - } - - #region private ================================================================================ - - private TemplateException() - { - // Not allowed, error code is required - } - - private TemplateException(string message) : base(message) - { - // Not allowed, error code is required - } - - private TemplateException(string message, Exception innerException) : base(message, innerException) - { - // Not allowed, error code is required - } - - #endregion }