2025-05-13 19:01:28 -07:00
export type ErrorType =
2025-09-21 11:02:31 -07:00
| "bad_request"
| "unauthorized"
| "forbidden"
| "not_found"
| "rate_limit"
| "offline" ;
2025-05-13 19:01:28 -07:00
export type Surface =
2025-09-21 11:02:31 -07:00
| "chat"
| "auth"
| "api"
| "stream"
| "database"
| "history"
| "vote"
| "document"
| "suggestions"
| "activate_gateway" ;
2025-05-13 19:01:28 -07:00
export type ErrorCode = ` ${ ErrorType } : ${ Surface } ` ;
2025-09-21 11:02:31 -07:00
export type ErrorVisibility = "response" | "log" | "none" ;
2025-05-13 19:01:28 -07:00
export const visibilityBySurface : Record < Surface , ErrorVisibility > = {
2025-09-21 11:02:31 -07:00
database : "log" ,
chat : "response" ,
auth : "response" ,
stream : "response" ,
api : "response" ,
history : "response" ,
vote : "response" ,
document : "response" ,
suggestions : "response" ,
activate_gateway : "response" ,
2025-05-13 19:01:28 -07:00
} ;
2026-02-23 17:24:17 -08:00
export class ChatbotError extends Error {
2025-09-21 11:02:31 -07:00
type : ErrorType ;
surface : Surface ;
statusCode : number ;
2025-05-13 19:01:28 -07:00
constructor ( errorCode : ErrorCode , cause? : string ) {
super ( ) ;
2025-09-21 11:02:31 -07:00
const [ type , surface ] = errorCode . split ( ":" ) ;
2025-05-13 19:01:28 -07:00
this . type = type as ErrorType ;
this . cause = cause ;
this . surface = surface as Surface ;
this . message = getMessageByErrorCode ( errorCode ) ;
this . statusCode = getStatusCodeByType ( this . type ) ;
}
2025-09-21 11:02:31 -07:00
toResponse() {
2025-05-13 19:01:28 -07:00
const code : ErrorCode = ` ${ this . type } : ${ this . surface } ` ;
const visibility = visibilityBySurface [ this . surface ] ;
const { message , cause , statusCode } = this ;
2025-09-21 11:02:31 -07:00
if ( visibility === "log" ) {
2025-05-13 19:01:28 -07:00
console . error ( {
code ,
message ,
cause ,
} ) ;
return Response . json (
2025-09-21 11:02:31 -07:00
{ code : "" , message : "Something went wrong. Please try again later." } ,
{ status : statusCode }
2025-05-13 19:01:28 -07:00
) ;
}
return Response . json ( { code , message , cause } , { status : statusCode } ) ;
}
}
export function getMessageByErrorCode ( errorCode : ErrorCode ) : string {
2025-09-21 11:02:31 -07:00
if ( errorCode . includes ( "database" ) ) {
return "An error occurred while executing a database query." ;
2025-05-13 19:01:28 -07:00
}
switch ( errorCode ) {
2025-09-21 11:02:31 -07:00
case "bad_request:api" :
2025-05-13 19:01:28 -07:00
return "The request couldn't be processed. Please check your input and try again." ;
2025-09-21 11:02:31 -07:00
case "bad_request:activate_gateway" :
return "AI Gateway requires a valid credit card on file to service requests. Please visit https://vercel.com/d?to=%2F%5Bteam%5D%2F%7E%2Fai%3Fmodal%3Dadd-credit-card to add a card and unlock your free credits." ;
case "unauthorized:auth" :
return "You need to sign in before continuing." ;
case "forbidden:auth" :
return "Your account does not have access to this feature." ;
case "rate_limit:chat" :
2026-03-20 09:37:02 +00:00
return "You've reached the message limit. Come back in 1 hour to continue chatting." ;
2025-09-21 11:02:31 -07:00
case "not_found:chat" :
return "The requested chat was not found. Please check the chat ID and try again." ;
case "forbidden:chat" :
return "This chat belongs to another user. Please check the chat ID and try again." ;
case "unauthorized:chat" :
return "You need to sign in to view this chat. Please sign in and try again." ;
case "offline:chat" :
2025-05-13 19:01:28 -07:00
return "We're having trouble sending your message. Please check your internet connection and try again." ;
2025-09-21 11:02:31 -07:00
case "not_found:document" :
return "The requested document was not found. Please check the document ID and try again." ;
case "forbidden:document" :
return "This document belongs to another user. Please check the document ID and try again." ;
case "unauthorized:document" :
return "You need to sign in to view this document. Please sign in and try again." ;
case "bad_request:document" :
return "The request to create or update the document was invalid. Please check your input and try again." ;
2025-05-13 19:01:28 -07:00
default :
2025-09-21 11:02:31 -07:00
return "Something went wrong. Please try again later." ;
2025-05-13 19:01:28 -07:00
}
}
function getStatusCodeByType ( type : ErrorType ) {
switch ( type ) {
2025-09-21 11:02:31 -07:00
case "bad_request" :
2025-05-13 19:01:28 -07:00
return 400 ;
2025-09-21 11:02:31 -07:00
case "unauthorized" :
2025-05-13 19:01:28 -07:00
return 401 ;
2025-09-21 11:02:31 -07:00
case "forbidden" :
2025-05-13 19:01:28 -07:00
return 403 ;
2025-09-21 11:02:31 -07:00
case "not_found" :
2025-05-13 19:01:28 -07:00
return 404 ;
2025-09-21 11:02:31 -07:00
case "rate_limit" :
2025-05-13 19:01:28 -07:00
return 429 ;
2025-09-21 11:02:31 -07:00
case "offline" :
2025-05-13 19:01:28 -07:00
return 503 ;
default :
return 500 ;
}
}