@juspay/neurolink
Version:
Universal AI Development Platform with working MCP integration, multi-provider support, and professional CLI. Built-in tools operational, 58+ external MCP servers discoverable. Connect to filesystem, GitHub, database operations, and more. Build, test, and
217 lines (216 loc) • 9.05 kB
JavaScript
/**
* Error handling system for Amazon SageMaker Provider
*
* This module provides comprehensive error handling, categorization,
* and user-friendly error messages for SageMaker operations.
*/
import { ERROR_MESSAGE_TEMPLATES, ERROR_MESSAGE_PREFIXES, RETRY_DELAYS, RETRYABLE_ERROR_CONDITIONS, ERROR_KEYWORDS, } from "./error-constants.js";
/**
* Custom error class for SageMaker-specific errors
*/
export class SageMakerError extends Error {
code;
statusCode;
cause;
endpoint;
requestId;
retryable;
constructor(message, code = "UNKNOWN_ERROR", statusCode, cause, endpoint, requestId, retryable = false) {
super(message);
this.name = "SageMakerError";
this.code = code;
this.statusCode = statusCode;
this.cause = cause;
this.endpoint = endpoint;
this.requestId = requestId;
this.retryable = retryable;
// Capture stack trace if available
if (Error.captureStackTrace) {
Error.captureStackTrace(this, SageMakerError);
}
}
/**
* Convert error to JSON for logging/serialization
*/
toJSON() {
return {
code: this.code,
message: this.message,
statusCode: this.statusCode,
cause: this.cause,
endpoint: this.endpoint,
requestId: this.requestId,
retryable: this.retryable,
stack: this.stack,
};
}
/**
* Get user-friendly error message with troubleshooting guidance
*/
getUserFriendlyMessage() {
return getSageMakerErrorGuidance(this.code, this.message, this.endpoint);
}
/**
* Check if this error type is retryable
*/
isRetryable() {
return this.retryable;
}
/**
* Get recommended retry delay in milliseconds
*/
getRetryDelay() {
return (RETRY_DELAYS[this.code] ||
RETRY_DELAYS.DEFAULT);
}
}
/**
* Main error handler for SageMaker operations
*
* @param error - Original error from AWS SDK or other operations
* @param endpoint - Endpoint name where error occurred (optional)
* @returns Categorized SageMakerError with user guidance
*/
export function handleSageMakerError(error, endpoint) {
// Handle cases where error is already a SageMakerError
if (error instanceof SageMakerError) {
return error;
}
// Handle standard Error objects
if (error instanceof Error) {
const errorName = error.name;
const errorMessage = error.message.toLowerCase();
// AWS SDK specific errors using centralized constants
if (errorName === "ValidationException" ||
ERROR_KEYWORDS.VALIDATION.some((keyword) => errorMessage.includes(keyword))) {
return new SageMakerError(`${ERROR_MESSAGE_PREFIXES.VALIDATION}: ${error.message}`, "VALIDATION_ERROR", 400, error, endpoint, extractRequestId(error), false);
}
if (errorName === "ModelError" ||
ERROR_KEYWORDS.MODEL.some((keyword) => errorMessage.includes(keyword))) {
return new SageMakerError(`${ERROR_MESSAGE_PREFIXES.MODEL}: ${error.message}`, "MODEL_ERROR", 500, error, endpoint, extractRequestId(error), false);
}
if (errorName === "InternalFailure" ||
ERROR_KEYWORDS.INTERNAL.some((keyword) => errorMessage.includes(keyword))) {
return new SageMakerError(`${ERROR_MESSAGE_PREFIXES.INTERNAL}: ${error.message}`, "INTERNAL_ERROR", 500, error, endpoint, extractRequestId(error), true);
}
if (errorName === "ServiceUnavailable" ||
ERROR_KEYWORDS.SERVICE_UNAVAILABLE.some((keyword) => errorMessage.includes(keyword))) {
return new SageMakerError(`${ERROR_MESSAGE_PREFIXES.SERVICE_UNAVAILABLE}: ${error.message}`, "SERVICE_UNAVAILABLE", 503, error, endpoint, extractRequestId(error), true);
}
if (errorName === "ThrottlingException" ||
ERROR_KEYWORDS.THROTTLING.some((keyword) => errorMessage.includes(keyword))) {
return new SageMakerError(`${ERROR_MESSAGE_PREFIXES.THROTTLING}: ${error.message}`, "THROTTLING_ERROR", 429, error, endpoint, extractRequestId(error), true);
}
if (errorName === "CredentialsError" ||
ERROR_KEYWORDS.CREDENTIALS.some((keyword) => errorMessage.includes(keyword))) {
return new SageMakerError(`${ERROR_MESSAGE_PREFIXES.CREDENTIALS}: ${error.message}`, "CREDENTIALS_ERROR", 401, error, endpoint, undefined, false);
}
if (errorName === "NetworkingError" ||
ERROR_KEYWORDS.NETWORK.some((keyword) => errorMessage.includes(keyword))) {
return new SageMakerError(`${ERROR_MESSAGE_PREFIXES.NETWORK}: ${error.message}`, "NETWORK_ERROR", 0, error, endpoint, undefined, true);
}
if (ERROR_KEYWORDS.ENDPOINT_NOT_FOUND.every((keyword) => errorMessage.includes(keyword))) {
return new SageMakerError(`${ERROR_MESSAGE_PREFIXES.ENDPOINT_NOT_FOUND}: ${error.message}`, "ENDPOINT_NOT_FOUND", 404, error, endpoint, extractRequestId(error), false);
}
// Generic error handling
return new SageMakerError(error.message, "UNKNOWN_ERROR", 500, error, endpoint, extractRequestId(error), false);
}
// Handle non-Error objects
const errorMessage = typeof error === "string" ? error : "Unknown error occurred";
return new SageMakerError(errorMessage, "UNKNOWN_ERROR", 500, undefined, endpoint, undefined, false);
}
/**
* Extract request ID from AWS SDK error for debugging
*
* @param error - Error object that might contain request ID
* @returns Request ID if found, undefined otherwise
*/
function extractRequestId(error) {
const errorAny = error;
return (errorAny.requestId ||
errorAny.RequestId ||
errorAny.$metadata?.requestId ||
undefined);
}
/**
* Get user-friendly error guidance based on error code
*
* @param code - SageMaker error code
* @param originalMessage - Original error message
* @param endpoint - Endpoint name (optional)
* @returns User-friendly error message with troubleshooting steps
*/
function getSageMakerErrorGuidance(code, originalMessage, endpoint) {
const endpointContext = endpoint ? ` (endpoint: ${endpoint})` : "";
// Get template for the error code, falling back to default
const template = ERROR_MESSAGE_TEMPLATES[code] || ERROR_MESSAGE_TEMPLATES.DEFAULT;
// Replace placeholders in the template
return template
.replace("{endpointContext}", endpointContext)
.replace("{originalMessage}", originalMessage);
}
/**
* Create a validation error for configuration issues
*
* @param message - Validation error message
* @param field - Configuration field that failed validation
* @returns SageMakerError with validation details
*/
export function createValidationError(message, field) {
const fullMessage = field
? `${ERROR_MESSAGE_PREFIXES.VALIDATION_FIELD} '${field}': ${message}`
: message;
return new SageMakerError(fullMessage, "VALIDATION_ERROR", 400);
}
/**
* Create a credentials error with setup guidance
*
* @param message - Credentials error message
* @returns SageMakerError with credentials guidance
*/
export function createCredentialsError(message) {
return new SageMakerError(`${ERROR_MESSAGE_PREFIXES.CREDENTIALS_SETUP}: ${message}`, "CREDENTIALS_ERROR", 401, undefined, undefined, undefined, false);
}
/**
* Create a network error with connectivity guidance
*
* @param message - Network error message
* @param endpoint - Endpoint that failed to connect
* @returns SageMakerError with network guidance
*/
export function createNetworkError(message, endpoint) {
return new SageMakerError(`${ERROR_MESSAGE_PREFIXES.NETWORK_CONNECTION}: ${message}`, "NETWORK_ERROR", 0, undefined, endpoint, undefined, true);
}
/**
* Check if an error is retryable based on its characteristics
*
* @param error - Error to check
* @returns True if the error suggests a retry might succeed
*/
export function isRetryableError(error) {
if (error instanceof SageMakerError) {
return error.isRetryable();
}
if (error instanceof Error) {
const errorMessage = error.message.toLowerCase();
const errorName = error.name;
// Check against retryable error names and message keywords
return (RETRYABLE_ERROR_CONDITIONS.ERROR_NAMES.includes(errorName) ||
RETRYABLE_ERROR_CONDITIONS.ERROR_MESSAGE_KEYWORDS.some((keyword) => errorMessage.includes(keyword)));
}
return false;
}
/**
* Get recommended retry delay for an error
*
* @param error - Error to get retry delay for
* @param attempt - Current retry attempt number (for exponential backoff)
* @returns Recommended delay in milliseconds
*/
export function getRetryDelay(error, attempt = 1) {
if (error instanceof SageMakerError) {
return error.getRetryDelay() * Math.pow(2, attempt - 1);
}
// Default exponential backoff
return 1000 * Math.pow(2, attempt - 1);
}