This error indicates your Firebase Cloud Function threw an unhandled exception. It happens when your code crashes without proper error handling, preventing the function from returning a valid response to the client.
When a Firebase callable function encounters an unhandled exception—whether from a failed database query, network timeout, syntax error, or uncaught promise rejection—Firebase returns an "INTERNAL - Unhandled exception" error to the client instead of your custom error. Callable functions must complete successfully or explicitly throw an HttpsError. Any other exception, including uncaught promise rejections and async errors, results in this generic error. This makes debugging difficult because the actual error message is hidden from the client and only visible in your Firebase Cloud Functions logs.
Open the Firebase Console and navigate to Functions > Logs to see the actual error message.
1. Go to https://console.firebase.google.com
2. Select your project
3. Click "Functions" in the left sidebar
4. Click the "Logs" tab
5. Find your function call and expand it to see the full error
The actual error will be more specific than "INTERNAL - Unhandled exception". Make note of the exact error type and message—this tells you what's actually failing in your code.
The most common cause is missing error handling. Every callable function should catch errors and throw HttpsError:
import * as functions from "firebase-functions";
export const myFunction = functions.https.onCall(async (data, context) => {
try {
// Your function logic here
const result = await someAsyncOperation(data);
return { success: true, data: result };
} catch (error) {
console.error("Error in myFunction:", error);
throw new functions.https.HttpsError(
"internal",
"An error occurred processing your request"
);
}
});This catches any exception and converts it to a proper HttpsError that the client can handle.
Unhandled promise rejections are a common cause. Make sure you await all promises:
// WRONG - Promise not awaited
export const myFunction = functions.https.onCall(async (data, context) => {
someAsyncFunction(); // Missing await
return { success: true };
});
// CORRECT - Promise is awaited
export const myFunction = functions.https.onCall(async (data, context) => {
await someAsyncFunction(); // Properly awaited
return { success: true };
});If a promise rejects and isn't awaited, the function exits before catching the error, resulting in the INTERNAL error.
Throw an HttpsError immediately if inputs are invalid:
export const myFunction = functions.https.onCall(async (data, context) => {
try {
// Validate inputs first
if (!data.userId) {
throw new functions.https.HttpsError(
"invalid-argument",
"userId is required"
);
}
if (!context.auth) {
throw new functions.https.HttpsError(
"unauthenticated",
"You must be logged in"
);
}
// Then process
const result = await processUser(data.userId);
return { success: true, data: result };
} catch (error) {
if (error instanceof functions.https.HttpsError) {
throw error; // Re-throw HttpsError
}
console.error("Unexpected error:", error);
throw new functions.https.HttpsError("internal", "An error occurred");
}
});Log errors to both Cloud Logging and Error Reporting:
import { logger } from "firebase-functions";
export const myFunction = functions.https.onCall(async (data, context) => {
try {
// Function logic
} catch (error) {
// Log to Cloud Logging and Error Reporting
logger.error("Error in myFunction", {
error: error instanceof Error ? error.message : String(error),
stack: error instanceof Error ? error.stack : undefined,
});
throw new functions.https.HttpsError(
"internal",
"An error occurred processing your request"
);
}
});This makes debugging easier because you can see detailed error information in the Firebase Console logs.
The emulator helps catch errors before deployment:
# Initialize emulator (if not already done)
firebase init emulators
# Start the emulator
firebase emulators:start --only functions
# In another terminal, test your function locally
firebase functions:shell
myFunction({userId: "123"})The emulator shows you the actual error instead of the generic "INTERNAL" error, making it much easier to debug.
Promise rejection chains: Be careful with promise chains. A rejected promise anywhere in the chain that isn't caught will cause an unhandled exception. Use .catch() or await/try-catch for all promises.
Firebase Admin SDK errors: When using the Firebase Admin SDK (Firestore, Realtime Database, Authentication), always wrap those calls in try-catch. Admin SDK operations can fail for permissions, network, or data validation reasons.
Network timeouts: External API calls or database queries that timeout without proper error handling will trigger this error. Set reasonable timeouts and catch timeout errors explicitly.
Serialization issues: Callable functions must return JSON-serializable data. Returning Firestore DocumentReferences, Date objects without conversion, or circular objects will cause serialization errors. Convert these to primitives before returning:
// WRONG - Firestore document not serializable
return { doc: firestoreDoc };
// CORRECT - Extract data and convert to primitive
return { data: firestoreDoc.data(), timestamp: firestoreDoc.get('createdAt').toMillis() };HTTP triggers vs callable: If you're using onRequest (HTTP trigger) instead of onCall, throwing HttpsError won't properly serialize. Always use onCall for client SDKs, or handle HTTP responses manually for onRequest.
auth/invalid-hash-algorithm: Hash algorithm doesn't match supported options
How to fix "auth/invalid-hash-algorithm: Hash algorithm doesn't match supported options" in Firebase
Hosting: CORS configuration not set up properly
How to fix CORS configuration in Firebase Hosting
auth/reserved-claims: Custom claims use reserved OIDC claim names
How to fix "reserved claims" error when setting custom claims in Firebase
Callable Functions: UNAUTHENTICATED - Invalid credentials
How to fix "UNAUTHENTICATED - Invalid credentials" in Firebase Callable Functions
messaging/message-rate-exceeded: Overall sending rate too high
Overall sending rate too high in Firebase Cloud Messaging