Overview
Advanced iMessage Kit uses Axios for HTTP requests and Socket.IO for real-time events. Understanding how to handle errors from both layers is essential for building reliable iMessage applications.
Error Types
HTTP Errors (Axios)
API calls throw Axios errors with structured response data:
try {
await sdk.messages.sendMessage({
chatGuid: "invalid-guid",
message: "test",
});
} catch (error: unknown) {
if (axios.isAxiosError(error)) {
console.error("Status:", error.response?.status);
console.error("Data:", error.response?.data);
console.error("Message:", error.message);
} else {
console.error("Unexpected error:", error);
}
}
Connection Errors
Socket.IO connection failures emit error events:
sdk.on("error", (error: Error) => {
console.error("Connection error:", error.message);
});
sdk.on("connect_error", (error) => {
console.error("Failed to connect:", error.message);
});
Source code reference: /home/daytona/workspace/source/client.ts:303-307, /home/daytona/workspace/source/client.ts:322-324
Message Send Errors
Failed message sends trigger dedicated events:
sdk.on("message-send-error", (data) => {
console.error("Failed to send message:");
console.error("GUID:", data.guid);
console.error("Text:", data.text);
console.error("Error:", data.error);
});
Source code reference: /home/daytona/workspace/source/types/events.ts:11
Common Error Scenarios
Chat Not Found
Occurs when sending to a non-existent chat:
try {
await sdk.messages.sendMessage({
chatGuid: "iMessage;-;+1234567890",
message: "Hello!",
});
} catch (error: unknown) {
if (axios.isAxiosError(error) && error.response?.status === 500) {
const errorMessage = error.response?.data?.message;
if (errorMessage?.includes("does not exist")) {
console.log("Chat doesn't exist - creating automatically");
// SDK auto-creates chat when using 'any;-;' prefix
}
}
}
The SDK includes automatic chat creation when using any;-;+number format. If the chat doesn’t exist, the SDK will create it and send the message.
Source code reference: /home/daytona/workspace/source/modules/message.ts:12-40
Authentication Failure
sdk.on("error", (error: Error) => {
if (error.message.includes("Authentication failed")) {
console.error("Invalid API key or server misconfiguration");
console.error("Check your credentials:");
console.error("- API key is correct");
console.error("- Server URL is accessible");
console.error("- Server requires authentication");
}
});
Source code reference: /home/daytona/workspace/source/client.ts:304-307
Network Timeout
import axios from "axios";
try {
const message = await sdk.messages.sendMessage({
chatGuid: "any;-;+1234567890",
message: "Hello!",
});
} catch (error: unknown) {
if (axios.isAxiosError(error)) {
if (error.code === "ECONNABORTED") {
console.error("Request timeout - server may be slow or unreachable");
} else if (error.code === "ECONNREFUSED") {
console.error("Connection refused - is the server running?");
}
}
}
Invalid Message GUID
try {
await sdk.messages.editMessage({
messageGuid: "invalid-guid",
editedMessage: "Updated text",
});
} catch (error: unknown) {
if (axios.isAxiosError(error) && error.response?.status === 400) {
console.error("Invalid message GUID or message not found");
}
}
Error Handling Patterns
Pattern 1: Basic Try-Catch
import { SDK } from "@photon-ai/advanced-imessage-kit";
const sdk = SDK();
sdk.on("ready", async () => {
try {
const message = await sdk.messages.sendMessage({
chatGuid: "any;-;+1234567890",
message: "Hello from MOBAI!",
});
console.log("Sent:", message.guid);
} catch (error: unknown) {
const message = error instanceof Error ? error.message : String(error);
console.error("Failed to send message:", message);
}
});
await sdk.connect();
Source code reference: /home/daytona/workspace/source/examples/message-send.ts:9-19
Pattern 2: Typed Error Handling
import axios from "axios";
function handleError(error: unknown, context: string) {
if (axios.isAxiosError(error)) {
const status = error.response?.status;
const data = error.response?.data;
console.error(`${context}:`);
console.error(`- Status: ${status}`);
console.error(`- Message: ${data?.message || error.message}`);
if (status === 404) {
console.error("- Resource not found");
} else if (status === 401 || status === 403) {
console.error("- Authentication required");
} else if (status === 500) {
console.error("- Server error");
}
} else if (error instanceof Error) {
console.error(`${context}: ${error.message}`);
} else {
console.error(`${context}: ${String(error)}`);
}
}
// Usage
try {
await sdk.messages.sendMessage({
chatGuid: "any;-;+1234567890",
message: "Hello!",
});
} catch (error) {
handleError(error, "Failed to send message");
}
Source code reference: /home/daytona/workspace/source/examples/utils.ts:24-31
Pattern 3: Retry Logic
async function sendMessageWithRetry(
sdk: AdvancedIMessageKit,
chatGuid: string,
message: string,
maxRetries = 3
) {
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
return await sdk.messages.sendMessage({ chatGuid, message });
} catch (error: unknown) {
if (axios.isAxiosError(error)) {
const status = error.response?.status;
// Don't retry client errors (4xx)
if (status && status >= 400 && status < 500) {
throw error;
}
}
if (attempt === maxRetries) {
throw error;
}
console.log(`Retry ${attempt}/${maxRetries}...`);
await new Promise(resolve => setTimeout(resolve, 1000 * attempt));
}
}
}
// Usage
try {
const message = await sendMessageWithRetry(
sdk,
"any;-;+1234567890",
"Hello!"
);
console.log("Sent:", message.guid);
} catch (error) {
console.error("Failed after retries:", error);
}
Pattern 4: Event-Based Error Handling
import { SDK } from "@photon-ai/advanced-imessage-kit";
const sdk = SDK({
serverUrl: "http://localhost:1234",
apiKey: process.env.API_KEY,
});
// Connection errors
sdk.on("error", (error: Error) => {
console.error("SDK Error:", error.message);
// Handle specific error types
if (error.message.includes("Authentication failed")) {
console.error("Check API key configuration");
process.exit(1);
}
});
sdk.on("connect_error", (error) => {
console.error("Connection Error:", error.message);
});
// Message send failures
sdk.on("message-send-error", (data) => {
console.error("Message Send Failed:");
console.error("- Message:", data.text);
console.error("- GUID:", data.guid);
console.error("- Error:", data.error);
// Implement retry logic or alert user
});
// Reconnection failures
sdk.socket.io.on("reconnect_failed", () => {
console.error("Reconnection failed after all attempts");
// Alert monitoring system or exit
});
await sdk.connect();
Best Practices
1. Always Use Type Guards
import axios from "axios";
try {
await sdk.messages.sendMessage({
chatGuid: "any;-;+1234567890",
message: "Hello!",
});
} catch (error: unknown) {
// ✓ Good - check error type first
if (axios.isAxiosError(error)) {
console.error("Axios error:", error.response?.status);
} else if (error instanceof Error) {
console.error("Error:", error.message);
} else {
console.error("Unknown error:", error);
}
// ✗ Bad - assumes error is Error type
// console.error((error as Error).message);
}
2. Check Response Status
import axios from "axios";
try {
await sdk.messages.sendMessage({
chatGuid: "iMessage;-;+1234567890",
message: "Hello!",
});
} catch (error: unknown) {
if (axios.isAxiosError(error)) {
const status = error.response?.status;
switch (status) {
case 400:
console.error("Invalid request parameters");
break;
case 401:
console.error("Unauthorized - check API key");
break;
case 404:
console.error("Chat or resource not found");
break;
case 500:
console.error("Server error");
break;
default:
console.error("Unexpected error:", status);
}
}
}
3. Handle Both Sync and Async Errors
// Handle async errors with try-catch
sdk.on("ready", async () => {
try {
await sdk.messages.sendMessage({
chatGuid: "any;-;+1234567890",
message: "Hello!",
});
} catch (error) {
console.error("Send failed:", error);
}
});
// Handle sync errors with event listeners
sdk.on("error", (error: Error) => {
console.error("Connection error:", error.message);
});
sdk.on("message-send-error", (data) => {
console.error("Message send error:", data);
});
await sdk.connect();
4. Implement Graceful Degradation
async function sendMessage(chatGuid: string, message: string) {
try {
return await sdk.messages.sendMessage({ chatGuid, message });
} catch (error: unknown) {
if (axios.isAxiosError(error)) {
const status = error.response?.status;
// Chat doesn't exist - try with 'any' prefix
if (status === 500 && chatGuid.startsWith("iMessage")) {
const address = chatGuid.split(";")[2];
console.log("Retrying with auto-detect...");
return await sdk.messages.sendMessage({
chatGuid: `any;-;${address}`,
message,
});
}
}
throw error;
}
}
5. Log Errors Appropriately
import { SDK } from "@photon-ai/advanced-imessage-kit";
const sdk = SDK({
serverUrl: "http://localhost:1234",
logLevel: "debug", // Use 'debug' for development, 'info' for production
});
sdk.on("error", (error: Error) => {
// Production: log to monitoring service
console.error("[ERROR]", {
timestamp: new Date().toISOString(),
message: error.message,
stack: error.stack,
});
});
try {
await sdk.messages.sendMessage({
chatGuid: "any;-;+1234567890",
message: "Hello!",
});
} catch (error: unknown) {
// Development: detailed error info
if (axios.isAxiosError(error)) {
console.error("Request failed:", {
status: error.response?.status,
data: error.response?.data,
config: error.config,
});
}
}
Error Recovery Strategies
Automatic Chat Creation
The SDK automatically creates chats when they don’t exist:
// This will auto-create the chat if needed
await sdk.messages.sendMessage({
chatGuid: "any;-;+1234567890",
message: "Hello!",
});
Source code reference: /home/daytona/workspace/source/modules/message.ts:20-38, /home/daytona/workspace/source/lib/auto-create-chat.ts
Connection Recovery
The SDK automatically reconnects on connection loss:
// SDK configuration (internal)
const socketConfig = {
reconnection: true,
reconnectionAttempts: Infinity, // Never give up
reconnectionDelay: 100, // Start with 100ms
reconnectionDelayMax: 2000, // Max 2 seconds
};
// Monitor reconnection
sdk.socket.io.on("reconnect", (attempt) => {
console.log(`Reconnected after ${attempt} attempt(s)`);
});
Source code reference: /home/daytona/workspace/source/client.ts:121-129
Message Deduplication
The SDK prevents duplicate message processing:
// Clear processed messages to prevent memory leaks
sdk.clearProcessedMessages(1000); // Keep last 1000 messages
// Check processed message count
const count = sdk.getProcessedMessageCount();
console.log(`Tracking ${count} processed messages`);
Source code reference: /home/daytona/workspace/source/client.ts:366-376, /home/daytona/workspace/source/client.ts:379-383
Complete Error Handling Example
import axios from "axios";
import { SDK } from "@photon-ai/advanced-imessage-kit";
import type { AdvancedIMessageKit } from "@photon-ai/advanced-imessage-kit";
const sdk = SDK({
serverUrl: process.env.SERVER_URL || "http://localhost:1234",
apiKey: process.env.API_KEY,
logLevel: "info",
});
// Connection error handling
sdk.on("error", (error: Error) => {
console.error("[SDK ERROR]", error.message);
if (error.message.includes("Authentication")) {
console.error("Fix authentication and restart");
process.exit(1);
}
});
sdk.on("connect_error", (error) => {
console.error("[CONNECTION ERROR]", error.message);
});
sdk.on("message-send-error", (data) => {
console.error("[MESSAGE SEND ERROR]", {
guid: data.guid,
text: data.text,
error: data.error,
});
});
// Reconnection monitoring
sdk.socket.io.on("reconnect_error", (error) => {
console.warn("[RECONNECT ERROR]", error.message);
});
sdk.socket.io.on("reconnect_failed", () => {
console.error("[RECONNECT FAILED] All attempts exhausted");
});
// API error handling
async function safeSendMessage(
chatGuid: string,
message: string
): Promise<void> {
try {
const result = await sdk.messages.sendMessage({ chatGuid, message });
console.log("✓ Sent:", result.guid);
} catch (error: unknown) {
if (axios.isAxiosError(error)) {
const status = error.response?.status;
const errorData = error.response?.data;
console.error("✗ Failed to send message:");
console.error(` Status: ${status}`);
console.error(` Message: ${errorData?.message || error.message}`);
switch (status) {
case 400:
console.error(" Reason: Invalid parameters");
break;
case 404:
console.error(" Reason: Chat not found");
break;
case 500:
console.error(" Reason: Server error");
break;
}
} else if (error instanceof Error) {
console.error("✗ Error:", error.message);
} else {
console.error("✗ Unknown error:", error);
}
throw error;
}
}
// Ready event
sdk.on("ready", async () => {
console.log("✓ SDK ready");
await safeSendMessage("any;-;+1234567890", "Hello!");
});
// Graceful shutdown
process.on("SIGINT", async () => {
console.log("\nShutting down...");
await sdk.close();
process.exit(0);
});
await sdk.connect();