Skip to main content
The @phala/cloud SDK provides a structured error hierarchy and two error handling patterns: throwing (default) and safe (result-based). This page covers how to catch and handle errors in the SDK. For the full list of ERR-xxxx error codes (returned by both the API and the CLI), see the Error Codes Reference.

Error Hierarchy

All API errors extend PhalaCloudError:
PhalaCloudError (base)
├── RequestError          — HTTP/network errors
├── ValidationError       — 422 validation errors (Pydantic)
├── AuthError             — 401/403 authentication errors
├── BusinessError         — 400/409 business logic errors
│   └── ResourceError     — Structured errors with ERR-xxxx codes
├── ServerError           — 500+ server errors
└── UnknownError          — Network issues, unexpected errors

Catching Errors

Using instanceof

import {
  PhalaCloudError,
  ValidationError,
  AuthError,
  BusinessError,
  ResourceError,
  ServerError,
} from "@phala/cloud";

try {
  await client.provisionCvm(payload);
} catch (error) {
  if (error instanceof ResourceError) {
    // Structured error with error code
    console.error(`Error [${error.errorCode}]: ${error.message}`);
    error.suggestions?.forEach((s) => console.log("Suggestion:", s));
  } else if (error instanceof ValidationError) {
    // Field-level validation errors
    error.validationErrors.forEach((e) => {
      console.error(`${e.field}: ${e.message}`);
    });
  } else if (error instanceof AuthError) {
    console.error("Authentication failed:", error.message);
  } else if (error instanceof BusinessError) {
    console.error("Business error:", error.message);
  } else if (error instanceof ServerError) {
    console.error("Server error:", error.message);
  }
}

Using Discriminator Properties

Each error class has a boolean discriminator property:
try {
  await client.provisionCvm(payload);
} catch (error) {
  if (error.isValidationError) {
    // error is ValidationError
  } else if (error.isAuthError) {
    // error is AuthError
  } else if (error.isResourceError) {
    // error is ResourceError (extends BusinessError)
  } else if (error.isBusinessError) {
    // error is BusinessError
  } else if (error.isServerError) {
    // error is ServerError
  } else if (error.isUnknownError) {
    // error is UnknownError
  }
}

Error Classes

PhalaCloudError

Base class for all errors. Properties:
PropertyTypeDescription
messagestringError message
statusnumberHTTP status code
statusTextstringHTTP status text
detailstring | Record<string, unknown> | Array<{ msg: string }>Raw error detail from API

ValidationError

Thrown on HTTP 422. Contains parsed field-level validation errors from FastAPI/Pydantic.
PropertyTypeDescription
isValidationErrortrueDiscriminator
validationErrorsValidationErrorItem[]Parsed validation errors
Each ValidationErrorItem:
{
  field: string;    // e.g., "name", "resources.memory"
  message: string;  // e.g., "String should have at least 4 characters"
  type: string;     // e.g., "string_too_short", "greater_than_equal"
  context?: Record<string, unknown>;  // e.g., { min_length: 4 }
}

AuthError

Thrown on HTTP 401 or 403.
PropertyTypeDescription
isAuthErrortrueDiscriminator

BusinessError

Thrown on HTTP 400, 409, and other 4xx errors.
PropertyTypeDescription
isBusinessErrortrueDiscriminator

ResourceError

Extends BusinessError. Thrown for structured errors with ERR-xxxx codes.
PropertyTypeDescription
isResourceErrortrueDiscriminator
errorCodestringError code (e.g., "ERR-01-001")
structuredDetailsStructuredErrorDetail[]Field-level details
suggestionsstring[]Suggested fixes
linksErrorLink[]Links to documentation

ServerError

Thrown on HTTP 500+.
PropertyTypeDescription
isServerErrortrueDiscriminator

UnknownError

Thrown for network issues or unexpected errors.
PropertyTypeDescription
isUnknownErrortrueDiscriminator

Safe Methods

Every action has a safe variant that returns SafeResult instead of throwing:
const result = await client.safeProvisionCvm(payload);

if (result.success) {
  console.log("Created:", result.data);
} else {
  // result.error is PhalaCloudError
  if (result.error instanceof ValidationError) {
    result.error.validationErrors.forEach((e) => {
      console.error(`${e.field}: ${e.message}`);
    });
  }
}
All safe methods follow the naming convention safe<ActionName>:
client.safeGetCurrentUser()
client.safeGetCvmInfo({ id: "..." })
client.safeProvisionCvm(payload)
client.safeDeleteCvm({ id: "..." })
// etc.

Formatting Utilities

formatValidationErrors(errors, options?)

Format validation errors for display:
import { ValidationError, formatValidationErrors } from "@phala/cloud";

if (error instanceof ValidationError) {
  const formatted = formatValidationErrors(error.validationErrors, {
    numbered: true,
    indent: 2,
    showFields: true,
  });
  console.error(formatted);
}
// Output:
//   1. name: String should have at least 4 characters
//   2. memory: Input should be greater than or equal to 1024
Options:
OptionTypeDefaultDescription
numberedbooleantrueNumber each error
indentnumber2Indent size in spaces
showFieldsbooleantrueShow field names

formatErrorMessage(error, options?)

Format any PhalaCloudError for display:
import { PhalaCloudError, formatErrorMessage } from "@phala/cloud";

if (error instanceof PhalaCloudError) {
  console.error(formatErrorMessage(error));
}
Options:
OptionTypeDefaultDescription
showFieldsbooleantrueShow field names in validation errors
showTypebooleanfalseInclude error class name

formatStructuredError(error, options?)

Format ResourceError with codes, details, suggestions, and links:
import { ResourceError, formatStructuredError } from "@phala/cloud";

if (error instanceof ResourceError) {
  console.error(formatStructuredError(error));
}
// Output:
// Error [ERR-01-001]: The requested instance type does not exist
//
// Details:
//   - Instance type 'invalid' is not recognized
//
// Suggestions:
//   - Use a valid instance type: tdx.small, tdx.medium, or tdx.large
//
// Learn more:
//   - View available instance types: https://cloud.phala.com/instances
Options:
OptionTypeDefaultDescription
showErrorCodebooleantrueShow error code in output
showSuggestionsbooleantrueShow suggestions
showLinksbooleantrueShow documentation links

Event-Based Error Handling

Listen to errors globally via the client event system:
const client = createClient({ apiKey: "your-api-key" });

client.on("error", (error) => {
  // Called for every API error, even when using safe methods
  if (error instanceof AuthError) {
    // Redirect to login
  }
});