Skip to main content

Billing Error Handling - Implementation Guide

Overview

The billing error handling system automatically detects and displays billing-related errors (insufficient credits, plan limits exceeded, etc.) to users via toast notifications.

Architecture

Components

  1. useBillingError Hook (lib/hooks/useBillingError.ts)

    • Detects billing errors from GraphQL/API responses
    • Formats errors for user display
    • Shows toast notifications
  2. useCreditCheck Hook (lib/hooks/useCreditCheck.ts)

    • Pre-operation credit validation
    • Shows warnings when balance is low
    • Prevents operations if insufficient credits
  3. Apollo Error Handler (graphql/apollo/apolloClient.ts)

    • Intercepts GraphQL errors
    • Emits billing errors via custom events
  4. BillingErrorToastHandler Component (components/providers/BillingErrorToastHandler.tsx)

    • Global listener for billing errors
    • Automatically shows toast notifications

Error Types

Billing Error Codes

CodeHTTP StatusUser Message
INSUFFICIENT_CREDITS402"You don't have enough credits to perform this operation"
PLAN_LIMIT_EXCEEDED403"You've reached the limit for this feature in your current plan"
SUBSCRIPTION_INACTIVE403"Your subscription is not active"
INVALID_PLAN_PRICING400"There's an issue with the pricing configuration"
BILLING_ERROR500"An unexpected billing error occurred"

Usage

1. Automatic Error Handling (No Code Required)

Billing errors are automatically displayed as toasts when they occur:

// Error is automatically caught, formatted, and displayed
await someAIOperation() // Will show error toast if it fails due to billing

2. Pre-Operation Credit Check

Check credits before starting an operation:

import { useCreditCheck } from "@hooks/useCreditCheck"

function CVParserPage() {
const { checkCredits, showCreditWarning, balance } = useCreditCheck()

const handleStartParsing = async () => {
// Assume CV parsing costs ~0.05 credits
const hasCredits = showCreditWarning({ estimatedCost: 0.05 })

if (!hasCredits) {
// User will see toast, operation won't proceed
return
}

// Proceed with operation
await parseCv(file)
}

return (
<div>
<p>Current Balance: {balance.toFixed(2)} credits</p>
<button onClick={handleStartParsing}>Parse CV</button>
</div>
)
}

3. Manual Error Detection and Handling

For custom error handling:

import { useBillingError } from "@hooks/useBillingError"

function CustomComponent() {
const { isBillingError, formatBillingError, showBillingErrorToast } = useBillingError()
const [execute] = useMutation(SOME_OPERATION)

const handleOperation = async () => {
try {
await execute()
} catch (error) {
if (isBillingError(error)) {
// Handle billing error
const { title, description } = formatBillingError(error)
console.log(`Billing Error: ${title} - ${description}`)

// Show custom dialog instead of toast
showDialog(title, description)
} else {
// Handle other errors
throw error
}
}
}

return <button onClick={handleOperation}>Do Operation</button>
}

4. Listen for Billing Errors Globally

For custom global error handling:

useEffect(() => {
const handleBillingError = (event: Event) => {
const customEvent = event as CustomEvent
const error = customEvent.detail

console.log("Billing error occurred:", error)
// Do something custom
}

window.addEventListener("billingError", handleBillingError)
return () => window.removeEventListener("billingError", handleBillingError)
}, [])

Integration Checklist

  • Apollo client error handler configured
  • BillingErrorToastHandler added to providers
  • useBillingError hook created
  • useCreditCheck hook created
  • TODO: Add credit checks to CV Parser page
  • TODO: Add credit checks to Job Creator page
  • TODO: Add credit checks to Agent Chat page
  • TODO: Add credit checks to Meeting Insights page

Pages to Update (Next Steps)

1. CV Parser Page

// app/company/cv-collection/parser.tsx
import { useCreditCheck } from "@hooks/useCreditCheck"

export function CVParser() {
const { showCreditWarning } = useCreditCheck()

const handleParseCV = async (file: File) => {
if (!showCreditWarning({ estimatedCost: 0.045 })) return
// Proceed with parsing
}
}

2. Job Creator Page

// app/company/jobs/create/page.tsx
import { useCreditCheck } from "@hooks/useCreditCheck"

export function JobCreatePage() {
const { showCreditWarning } = useCreditCheck()

const handleCreateJob = async (jobData) => {
if (!showCreditWarning({ estimatedCost: 0.10 })) return
// Proceed with creation
}
}

3. Agent Chat Page

// app/company/chatbot/page.tsx
import { useCreditCheck } from "@hooks/useCreditCheck"

export function AgentChatPage() {
const { showCreditWarning } = useCreditCheck()

const handleSendMessage = async (message: string) => {
// Costs vary by model, estimate conservatively
if (!showCreditWarning({ estimatedCost: 0.02 })) return
// Proceed with message
}
}

Testing

Test Insufficient Credits

  1. Set credit balance to 0 in database
  2. Try to execute any AI operation
  3. Verify error toast appears with message: "You don't have enough credits..."

Test Plan Limit Exceeded

  1. Exceed plan limit for a feature (e.g., 100 CV parsings/month)
  2. Try to parse another CV
  3. Verify error toast appears with message: "You've reached the limit..."

Test Subscription Inactive

  1. Set subscription status to CANCELED
  2. Try to execute an operation
  3. Verify error toast appears with message: "Your subscription is not active"

Customization

Change Toast Position

Edit app/providers.tsx:

<TWToastProvider placement="bottom-right"> {/* default: top-right */}

Change Toast Duration

Edit useBillingError.ts - modify timeout values:

addTWToast({
timeout: 10000 // milliseconds
})

Add Custom Error Messages

Edit useBillingError.ts:

export const BILLING_ERROR_MESSAGES = {
INSUFFICIENT_CREDITS: {
title: "Custom Title",
description: "Custom description"
},
// ...
}