How to fix Callable Functions: INTERNAL - Unhandled exception in Firebase
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.
Quick fix
Fixes INTERNAL
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"
);
}
});- Check Firebase Cloud Functions logs
- Wrap your function logic in try-catch
- Ensure all async operations are awaited
- Validate inputs before processing
import * as functions from "firebase-functions";export const myFunction = functions.https.onCall(async (data, context) => {try {// Your function logic hereconst 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");}});Callable Functions: INTERNAL - Unhandled exception
What this error means
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.
Typical symptoms
- Client receives 'INTERNAL - Unhandled exception' error when calling a Cloud Function
- Function works locally in the emulator but fails in production
- Error appears on the client but no clear message about what went wrong
- Firebase Console shows the function invocation in the logs but the response is incomplete
Common causes
- Unhandled promise rejection or missing await keyword in async code
- Database query or API call fails without a try-catch block
- Throwing a regular Error instead of HttpsError from the function
- Code path throws an exception before the function returns a value
- Third-party library or SDK throws an error that isn't caught
- Using HttpsError with onRequest (HTTP trigger) instead of onCall (callable trigger)
How to fix "Callable Functions: INTERNAL - Unhandled exception"
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.
Advanced notes
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.
Frequently asked questions
- What does "INTERNAL" mean?
- 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.
- How do I fix "INTERNAL"?
- 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.
- What causes "INTERNAL"?
- Unhandled promise rejection or missing await keyword in async code Database query or API call fails without a try-catch block Throwing a regular Error instead of HttpsError from the function
- Is the "INTERNAL" error serious?
- Yes. This is a high-severity error that usually blocks work until it is fixed, but the steps above resolve it.
Official resources & further reading
- 📚Firebase Official Documentation
- 📖Firebase: Call functions from your app(Official Docs)
- 📖Firebase: Report errors from Cloud Functions(Official Docs)
- 🐙
- 🐙