CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-qiniu-js

JavaScript SDK for Qiniu Cloud Storage that enables browser-based file uploads with resumable transfer, image processing, and comprehensive error handling.

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

error-handling.mddocs/

Error Handling

Comprehensive error handling system with specific error types for different failure scenarios and automatic retry mechanisms.

Capabilities

Error Types

The SDK provides a hierarchical error system for precise error handling and debugging.

enum QiniuErrorName {
  // Input validation errors
  InvalidFile = 'InvalidFile',
  InvalidToken = 'InvalidToken', 
  InvalidMetadata = 'InvalidMetadata',
  InvalidChunkSize = 'InvalidChunkSize',
  InvalidCustomVars = 'InvalidCustomVars',
  NotAvailableUploadHost = 'NotAvailableUploadHost',
  
  // Cache and resume functionality errors
  ReadCacheFailed = 'ReadCacheFailed',
  InvalidCacheData = 'InvalidCacheData',
  WriteCacheFailed = 'WriteCacheFailed',
  RemoveCacheFailed = 'RemoveCacheFailed',
  
  // Image compression errors
  GetCanvasContextFailed = 'GetCanvasContextFailed',
  UnsupportedFileType = 'UnsupportedFileType',
  
  // Browser environment errors
  FileReaderReadFailed = 'FileReaderReadFailed',
  NotAvailableXMLHttpRequest = 'NotAvailableXMLHttpRequest',
  InvalidProgressEventTarget = 'InvalidProgressEventTarget',
  
  // Network and server errors
  RequestError = 'RequestError'
}

Base Error Class

Foundation error class for all SDK errors.

/**
 * Base error class for all Qiniu SDK errors
 */
class QiniuError implements Error {
  public stack: string | undefined;
  
  constructor(public name: QiniuErrorName, public message: string);
}

Usage Example:

import { QiniuError, QiniuErrorName } from "qiniu-js";

try {
  // Some SDK operation
} catch (error) {
  if (error instanceof QiniuError) {
    switch (error.name) {
      case QiniuErrorName.InvalidFile:
        console.error('File validation failed:', error.message);
        break;
      case QiniuErrorName.InvalidToken:
        console.error('Token is invalid or expired:', error.message);
        break;
      default:
        console.error('SDK error:', error.message);
    }
  }
}

Request Error Class

Specific error type for HTTP request failures with server response details.

/**
 * Error class for HTTP request failures
 */
class QiniuRequestError extends QiniuError {
  /** 
   * Legacy property for error type identification
   * @deprecated Use instanceof instead
   */
  public isRequestError = true;
  
  /** Server response data if available */
  public data?: any;
  
  constructor(
    public code: number,
    public reqId: string, 
    message: string,
    data?: any
  );
}

Usage Example:

import { upload, QiniuRequestError } from "qiniu-js";

const subscription = upload(file, key, token).subscribe({
  error: (error) => {
    if (error instanceof QiniuRequestError) {
      console.error(`Request failed with HTTP ${error.code}`);
      console.error(`Request ID: ${error.reqId}`);
      
      if (error.data) {
        console.error('Server response:', error.data);
      }
      
      // Handle specific HTTP codes
      switch (error.code) {
        case 401:
          console.error('Unauthorized - check your token');
          break;
        case 403:
          console.error('Forbidden - insufficient permissions');
          break;
        case 413:
          console.error('File too large');
          break;
        case 599:
          console.error('Server timeout - will retry automatically');
          break;
        default:
          console.error('Request error:', error.message);
      }
    }
  }
});

Network Error Class

Specialized error for network connectivity issues.

/**
 * Error class for network connectivity issues
 * Covers CORS, certificate, DNS, and connection failures
 */
class QiniuNetworkError extends QiniuRequestError {
  constructor(message: string, reqId?: string);
}

Usage Example:

import { upload, QiniuNetworkError, QiniuRequestError } from "qiniu-js";

const subscription = upload(file, key, token).subscribe({
  error: (error) => {
    if (error instanceof QiniuNetworkError) {
      console.error('Network connectivity issue:', error.message);
      // Suggest user checks connection, firewall, etc.
      showNetworkErrorMessage();
    } else if (error instanceof QiniuRequestError) {
      console.error('Server request failed:', error.message);
      // Handle server-side errors
    } else {
      console.error('Other error:', error.message);
      // Handle validation and other errors
    }
  }
});

Error Handling Patterns

Comprehensive Error Handling

Complete error handling strategy covering all error types.

import { 
  upload, 
  QiniuError, 
  QiniuRequestError, 
  QiniuNetworkError,
  QiniuErrorName 
} from "qiniu-js";

function handleUpload(file: File, key: string, token: string) {
  const subscription = upload(file, key, token, {
    fname: file.name
  }, {
    retryCount: 3,
    region: 'z0'
  }).subscribe({
    next: (progress) => {
      updateProgressUI(progress.total.percent);
    },
    error: (error) => {
      if (error instanceof QiniuNetworkError) {
        // Network issues - suggest user actions
        showErrorMessage('Network connection failed. Please check your internet connection and try again.');
        logError('network', error);
        
      } else if (error instanceof QiniuRequestError) {
        // Server errors - handle based on HTTP code
        const isRetryable = [502, 503, 504, 599].includes(error.code);
        
        if (isRetryable) {
          showErrorMessage('Server temporarily unavailable. The upload will retry automatically.');
        } else if (error.code === 401) {
          showErrorMessage('Upload token expired. Please refresh and try again.');
          refreshToken();
        } else if (error.code === 413) {
          showErrorMessage('File is too large for upload.');
        } else {
          showErrorMessage(`Upload failed: ${error.message}`);
        }
        
        logError('request', error, { code: error.code, reqId: error.reqId });
        
      } else if (error instanceof QiniuError) {
        // SDK validation and runtime errors
        switch (error.name) {
          case QiniuErrorName.InvalidFile:
            showErrorMessage('Invalid file selected. Please choose a different file.');
            break;
          case QiniuErrorName.InvalidToken:
            showErrorMessage('Upload token is invalid. Please refresh and try again.');
            refreshToken();
            break;
          case QiniuErrorName.UnsupportedFileType:
            showErrorMessage('File type not supported for compression.');
            break;
          case QiniuErrorName.GetCanvasContextFailed:
            showErrorMessage('Image processing failed. Browser may not support required features.');
            break;
          default:
            showErrorMessage(`Upload failed: ${error.message}`);
        }
        
        logError('sdk', error);
        
      } else {
        // Unexpected errors
        showErrorMessage('An unexpected error occurred. Please try again.');
        logError('unknown', error);
      }
    },
    complete: (response) => {
      showSuccessMessage('File uploaded successfully!');
      console.log('Upload result:', response);
    }
  });
  
  return subscription;
}

// Helper functions
function showErrorMessage(message: string) {
  // Update UI with error message
  document.getElementById('error-message').textContent = message;
}

function showSuccessMessage(message: string) {
  // Update UI with success message
  document.getElementById('success-message').textContent = message;
}

function updateProgressUI(percent: number) {
  // Update progress bar
  document.getElementById('progress-bar').style.width = `${percent}%`;
}

function logError(type: string, error: any, extra?: any) {
  // Send error to logging service
  console.error(`[${type}] Upload error:`, error, extra);
}

function refreshToken() {
  // Request new token from server
  // Implementation depends on your authentication system
}

Retry Logic and Error Recovery

The SDK automatically handles retries for certain error conditions:

// Errors that trigger automatic retry
const RETRY_CODE_LIST = [0, 502, 503, 504, 599, 406];

// Errors that cause host switching
const FREEZE_CODE_LIST = [0, 502, 503, 504, 599];

Custom Retry Configuration:

import { upload } from "qiniu-js";

// Configure retry behavior
const uploadWithRetry = upload(file, key, token, {
  fname: file.name
}, {
  retryCount: 5, // Retry up to 5 times
  region: 'z0'
}).subscribe({
  error: (error) => {
    if (error instanceof QiniuRequestError) {
      console.log(`Failed after ${5} retry attempts`);
    }
  }
});

Validation Error Prevention

Prevent common validation errors by checking inputs before upload:

import { QiniuError, QiniuErrorName } from "qiniu-js";

function validateUploadInputs(file: File, token: string, putExtra?: any): string | null {
  // File validation
  if (!file || file.size === 0) {
    return 'Please select a valid file';
  }
  
  if (file.size > 10000 * 1024 * 1024 * 1024) { // 10TB limit
    return 'File size exceeds maximum limit of 10TB';
  }
  
  // Token validation
  if (!token || typeof token !== 'string') {
    return 'Upload token is required';
  }
  
  // Custom variables validation
  if (putExtra?.customVars) {
    for (const key of Object.keys(putExtra.customVars)) {
      if (!key.startsWith('x:')) {
        return `Custom variable key '${key}' must start with 'x:'`;
      }
    }
  }
  
  // Metadata validation
  if (putExtra?.metadata) {
    for (const key of Object.keys(putExtra.metadata)) {
      if (!key.startsWith('x-qn-meta-')) {
        return `Metadata key '${key}' must start with 'x-qn-meta-'`;
      }
    }
  }
  
  return null; // No validation errors
}

// Use validation before upload
function safeUpload(file: File, key: string, token: string, putExtra?: any) {
  const validationError = validateUploadInputs(file, token, putExtra);
  
  if (validationError) {
    console.error('Validation failed:', validationError);
    return;
  }
  
  return upload(file, key, token, putExtra);
}

Install with Tessl CLI

npx tessl i tessl/npm-qiniu-js

docs

configuration.md

error-handling.md

image-processing.md

index.md

upload.md

utilities.md

tile.json