TypeScript SDK
Error Handling

Error Handling

The HiveForge SDK uses a hierarchy of error classes to help you handle different failure modes. All errors extend the standard Error class and include machine-readable codes for programmatic handling.

Error Classes

HiveForgeError

The base error class for all HiveForge API errors. Thrown by the core client when API requests fail.

import { HiveForgeError } from '@producthacker/hiveforge-sdk';
 
try {
  await hiveforge.initialize();
} catch (error) {
  if (error instanceof HiveForgeError) {
    console.error('Message:', error.message);
    console.error('Code:', error.code);      // e.g., 'invalid_credentials'
    console.error('Status:', error.status);   // HTTP status code, e.g., 401
  }
}

Properties:

PropertyTypeDescription
messagestringHuman-readable error message
codestring | undefinedMachine-readable error code
statusnumber | undefinedHTTP status code from the API

AIProxyException

Thrown by AI proxy methods (hiveforge.ai.*). Includes quota-specific properties.

import { AIProxyException } from '@producthacker/hiveforge-sdk';
 
try {
  const response = await hiveforge.ai.complete({
    messages: [{ role: 'user', content: 'Hello!' }],
  });
} catch (error) {
  if (error instanceof AIProxyException) {
    console.error('Code:', error.code);
    console.error('Message:', error.message);
 
    if (error.isQuotaExceeded) {
      console.log('Quota exceeded!');
      if (error.upgradeUrl) {
        console.log('Upgrade at:', error.upgradeUrl);
      }
    }
  }
}

Properties:

PropertyTypeDescription
messagestringError message
codestringError code (e.g., 'quota_exceeded', 'ai_disabled')
isQuotaExceededbooleanWhether this is a quota exceeded error
upgradeUrlstring | undefinedURL to upgrade the subscription
detailsAIProxyErrorFull error details from the API

AIProxyError details object:

FieldTypeDescription
errorstringError type
codestringError code
messagestringError message
upgrade_urlstringOptional upgrade URL
quota_exceededbooleanWhether quota was exceeded

BillingProxyException

Thrown by billing proxy methods (hiveforge.billing.*).

import { BillingProxyException } from '@producthacker/hiveforge-sdk';
 
try {
  const checkout = await hiveforge.billing.createCheckout({
    priceId: 'price_1N2b3c4D5e6F7g8H9i0J',
    customerEmail: 'jane@example.com',
    successUrl: '/success',
    cancelUrl: '/cancel',
  });
} catch (error) {
  if (error instanceof BillingProxyException) {
    console.error(`Billing error [${error.code}]: ${error.message}`);
  }
}

Properties:

PropertyTypeDescription
messagestringError message
codestringError code (e.g., 'billing_disabled', 'stripe_error')
detailsBillingProxyErrorFull error details

EmailProxyException

Thrown by email proxy methods (hiveforge.email.*). Includes credit information for credit-related failures.

import { EmailProxyException } from '@producthacker/hiveforge-sdk';
 
try {
  await hiveforge.email.send({
    to: ['jane@example.com'],
    subject: 'Hello',
    html: '<p>Hi!</p>',
  });
} catch (error) {
  if (error instanceof EmailProxyException) {
    console.error(`Email error [${error.code}]: ${error.message}`);
    if (error.creditsRequired !== undefined) {
      console.log(`Need ${error.creditsRequired} credits, have ${error.creditsAvailable}`);
    }
  }
}

Properties:

PropertyTypeDescription
messagestringError message
codestringError code
creditsRequirednumber | undefinedCredits needed for the operation
creditsAvailablenumber | undefinedCredits currently available

VectorProxyException

Thrown by vector proxy methods (hiveforge.vectors.*).

import { VectorProxyException } from '@producthacker/hiveforge-sdk';
 
try {
  await hiveforge.vectors.search({ query: 'test' });
} catch (error) {
  if (error instanceof VectorProxyException) {
    console.error(`Vector error [${error.code}]: ${error.message}`);
    if (error.creditsRequired !== undefined) {
      console.log(`Need ${error.creditsRequired} credits, have ${error.creditsAvailable}`);
    }
  }
}

Properties: Same as EmailProxyException.


WebhookProxyException

Thrown by webhook proxy methods (hiveforge.webhooks.*).

import { WebhookProxyException } from '@producthacker/hiveforge-sdk';
 
try {
  await hiveforge.webhooks.send({
    url: 'https://api.partner.com/webhooks',
    payload: { event: 'test' },
  });
} catch (error) {
  if (error instanceof WebhookProxyException) {
    console.error(`Webhook error [${error.code}]: ${error.message}`);
  }
}

Properties: Same as EmailProxyException.

Common Error Patterns

Handling Quota Exceeded

import { AIProxyException, HiveForgeError } from '@producthacker/hiveforge-sdk';
 
async function safeAIComplete(messages: Array<{ role: string; content: string }>) {
  try {
    return await hiveforge.ai.complete({
      messages: messages as any,
    });
  } catch (error) {
    if (error instanceof AIProxyException && error.isQuotaExceeded) {
      // Option 1: Redirect to upgrade
      if (typeof window !== 'undefined' && error.upgradeUrl) {
        window.location.href = error.upgradeUrl;
        return null;
      }
 
      // Option 2: Return a fallback response
      return {
        content: 'AI quota exceeded. Please upgrade your plan for continued access.',
        model: 'fallback',
        tokens_used: 0,
        tokens_input: 0,
        tokens_output: 0,
        finish_reason: 'quota_exceeded',
      };
    }
    throw error;
  }
}

Handling Authentication Errors

try {
  await hiveforge.initialize();
} catch (error) {
  if (error instanceof HiveForgeError) {
    switch (error.status) {
      case 401:
        console.error('Invalid deployment credentials. Check HIVEFORGE_DEPLOYMENT_ID and HIVEFORGE_DEPLOYMENT_SECRET.');
        break;
      case 403:
        console.error('Deployment is not authorized for this action.');
        break;
      case 404:
        console.error('Deployment not found. Verify your deployment ID.');
        break;
      default:
        console.error(`API error (${error.status}): ${error.message}`);
    }
  }
}

Handling Credit Exhaustion Across Services

import {
  EmailProxyException,
  VectorProxyException,
  WebhookProxyException,
} from '@producthacker/hiveforge-sdk';
 
type CreditError = EmailProxyException | VectorProxyException | WebhookProxyException;
 
function isCreditError(error: unknown): error is CreditError {
  return (
    (error instanceof EmailProxyException ||
     error instanceof VectorProxyException ||
     error instanceof WebhookProxyException) &&
    error.creditsRequired !== undefined
  );
}
 
async function withCreditCheck<T>(operation: () => Promise<T>): Promise<T> {
  try {
    return await operation();
  } catch (error) {
    if (isCreditError(error)) {
      console.error(
        `Insufficient credits: need ${error.creditsRequired}, have ${error.creditsAvailable}`
      );
      // Notify user or purchase more credits
      throw new Error('Insufficient credits. Please purchase a credit pack to continue.');
    }
    throw error;
  }
}
 
// Usage
const result = await withCreditCheck(() =>
  hiveforge.email.send({
    to: ['jane@example.com'],
    subject: 'Hello',
    html: '<p>Hi!</p>',
  })
);

Retry Pattern with Exponential Backoff

import { HiveForgeError } from '@producthacker/hiveforge-sdk';
 
async function withRetry<T>(
  operation: () => Promise<T>,
  maxRetries = 3,
  baseDelayMs = 1000
): Promise<T> {
  for (let attempt = 0; attempt <= maxRetries; attempt++) {
    try {
      return await operation();
    } catch (error) {
      // Don't retry client errors (4xx) except rate limits (429)
      if (error instanceof HiveForgeError) {
        if (error.status && error.status >= 400 && error.status < 500 && error.status !== 429) {
          throw error;
        }
      }
 
      if (attempt === maxRetries) {
        throw error;
      }
 
      const delay = baseDelayMs * Math.pow(2, attempt);
      console.log(`Attempt ${attempt + 1} failed, retrying in ${delay}ms...`);
      await new Promise(resolve => setTimeout(resolve, delay));
    }
  }
 
  // TypeScript requires this, but it's unreachable
  throw new Error('Retry failed');
}
 
// Usage
const response = await withRetry(() =>
  hiveforge.ai.complete({
    messages: [{ role: 'user', content: 'Hello!' }],
  })
);

Using the Event System for Error Monitoring

// Set up global error monitoring
hiveforge.on('entitlements:error', (error) => {
  // Log to your error tracking service
  console.error('Entitlement refresh failed:', error.message);
  // e.g., Sentry.captureException(error);
});
 
hiveforge.on('quota:exceeded', ({ resource, used, limit }) => {
  console.error(`Quota exceeded for ${resource}: ${used}/${limit}`);
  // Notify admin, send alert, etc.
});
 
hiveforge.on('quota:warning', ({ resource, used, limit }) => {
  const percent = Math.round((used / limit) * 100);
  console.warn(`${resource} quota at ${percent}%`);
});
 
hiveforge.on('status:changed', ({ previous, current }) => {
  if (current === 'suspended') {
    console.error('Deployment has been suspended!');
    // Take action: notify user, disable features, etc.
  }
});

Comprehensive Error Handler

import {
  HiveForgeError,
  AIProxyException,
  BillingProxyException,
  EmailProxyException,
  VectorProxyException,
  WebhookProxyException,
} from '@producthacker/hiveforge-sdk';
 
function handleHiveForgeError(error: unknown): string {
  if (error instanceof AIProxyException) {
    if (error.isQuotaExceeded) {
      return 'AI usage limit reached. Please upgrade your plan.';
    }
    return `AI service error: ${error.message}`;
  }
 
  if (error instanceof BillingProxyException) {
    return `Billing error: ${error.message}`;
  }
 
  if (error instanceof EmailProxyException) {
    if (error.creditsRequired) {
      return `Not enough credits to send email. Need ${error.creditsRequired}, have ${error.creditsAvailable}.`;
    }
    return `Email error: ${error.message}`;
  }
 
  if (error instanceof VectorProxyException) {
    if (error.creditsRequired) {
      return `Not enough credits for vector operation. Need ${error.creditsRequired}, have ${error.creditsAvailable}.`;
    }
    return `Vector search error: ${error.message}`;
  }
 
  if (error instanceof WebhookProxyException) {
    return `Webhook delivery error: ${error.message}`;
  }
 
  if (error instanceof HiveForgeError) {
    return `HiveForge error (${error.status ?? 'unknown'}): ${error.message}`;
  }
 
  if (error instanceof Error) {
    return error.message;
  }
 
  return 'An unexpected error occurred';
}