Firebase云函数构建报错:Maximum call stack size exceeded 求助
问题描述
我写了一个用于读取文档并返回结果的Firebase云函数,构建时遇到以下错误:
Error: Failed to load function definition from source: Failed to generate manifest from function source: RangeError: Maximum call stack size exceeded
函数代码如下:
exports.getConfiguration = functions.region("asia-northeast3") .https.onCall(async(data, context) => { let userConfigData: any; let accountData: any; let sysConfigData: any; if (context.auth == null) { throw new functions.https.HttpsError('unauthenticated', 'The request does not have valid authentication credentials for the operation.'); } const uid = context.auth!.uid; const accountRef = firestoreDb.collection('accounts').doc(uid); const userConfigRef = firestoreDb.collection('accounts').doc(uid).collection('configuration').doc(uid); const sysConfigRef = firestoreDb.collection('configuration').doc('platform'); try { await accountRef.get().then(async (doc) => { const result = doc.data(); if ( result ==null) { const user = await admin.auth().getUser(uid); accountData = { 'uid': uid, 'displayName': user.displayName || null, 'email': user.email || null, 'emailVerified': user.emailVerified || null, 'phoneNumber': user.phoneNumber || null, 'photo': user.photoURL || null, 'status': 'newUser', 'language': 'english', 'createdAt': timeStamp.now().toMillis(), }; await accountRef.set(accountData); userConfigData = null; } else { userConfigData = await userConfigRef.get().then((doc) => doc.data()); } } ); sysConfigData = await sysConfigRef.get().then((doc) => doc.data()); } catch (e) { console.log("Error: ", e); throw new functions.https.HttpsError('unknown', 'Unknown error or an error from a different error domain.'); } return {accountData, userConfigData, sysConfigData}; });
解决方案
栈溢出错误的核心原因是你在async函数里混用了await和.then(),导致Promise嵌套逻辑混乱,触发调用栈溢出。另外代码里还有几个潜在问题,下面是修复后的完整代码:
exports.getConfiguration = functions.region("asia-northeast3") .https.onCall(async(data, context) => { let userConfigData: any; let accountData: any; let sysConfigData: any; if (!context.auth) { throw new functions.https.HttpsError('unauthenticated', '请求未携带有效认证凭证'); } const uid = context.auth.uid; const accountRef = firestoreDb.collection('accounts').doc(uid); const userConfigRef = firestoreDb.collection('accounts').doc(uid).collection('configuration').doc(uid); const sysConfigRef = firestoreDb.collection('configuration').doc('platform'); try { // 统一用await替代.then(),彻底避免嵌套混乱 const accountDoc = await accountRef.get(); const accountResult = accountDoc.data(); if (!accountResult) { const user = await admin.auth().getUser(uid); accountData = { uid, displayName: user.displayName || null, email: user.email || null, emailVerified: user.emailVerified || null, phoneNumber: user.phoneNumber || null, photo: user.photoURL || null, status: 'newUser', language: 'english', createdAt: admin.firestore.Timestamp.now().toMillis(), }; await accountRef.set(accountData); userConfigData = null; } else { const userConfigDoc = await userConfigRef.get(); userConfigData = userConfigDoc.data(); } const sysConfigDoc = await sysConfigRef.get(); sysConfigData = sysConfigDoc.data(); } catch (e) { console.error("错误详情: ", e); throw new functions.https.HttpsError('unknown', '未知错误,请检查日志'); } return { accountData, userConfigData, sysConfigData }; });
关键修复点:
- 彻底移除
.then()嵌套,统一使用await处理异步操作,避免Promise链逻辑混乱 - 修正
timeStamp为Firebase官方的admin.firestore.Timestamp(原代码里的timeStamp可能未正确引入,属于潜在问题) - 简化空值判断逻辑,让代码更简洁
- 把日志输出改为
console.error,便于区分错误信息
如果本地部署后仍出现栈溢出,建议排查:
- 其他函数是否存在递归调用问题
- Firebase Admin SDK是否正确初始化(比如
firestoreDb是否是admin.firestore()的正确引用) - 本地Node.js版本是否和Firebase Functions要求的版本匹配
内容的提问来源于stack exchange,提问作者Patrick SINT
相关产品推荐
相关产品推荐

