# EdgeOne Pages 技术支持工单:(CLOUD_FUNCTION_INVOCATION_FAILED)
> 提交对象:腾讯云 EdgeOne Pages 技术支持
> 站点 / 域名:`heimaojiaodui.com`
> Pages 项目:`ai-proofreading`(Git 集成,框架预设 Next.js)
> 现象:Pages 构建成功、Cloud Function 部署成功,但访问任何页面返回 **502 CLOUD_FUNCTION_INVOCATION_FAILED**,且**控制台「日志分析」在任何时间范围 / 环境 / 日志级别下均无任何日志**。
> 对照事实:**完全相同的 Next.js standalone 构建产物,在普通 Node 容器(Railway)上运行完全正常(首页 200)**,仅 EdgeOne Cloud Functions 运行时失败。
---
## 1. 我们需要 EdgeOne 协助的核心问题(TL;DR)
1. **【最关键】如何获取 Cloud Function 运行时的崩溃日志 / 堆栈?** 函数被调用即 502,但控制台「日志分析」完全为空(已尝试:生产 / 预览环境、15 分钟 / 24 小时、全部日志 / 失败日志,均无)。我们怀疑函数在**请求处理 / 冷启动早期**就崩溃,崩在应用 `console` 之前,导致平台未捕获。请问是否有办法拿到该函数的 stderr / 运行时错误堆栈?
2. **请确认 Cloud Function(Node.js)运行时环境细节**:精确 Node.js 版本、CPU 架构(x64 / arm64)、libc(glibc / musl)、内存上限、冷启动超时。文档只标注"v20.x"。
3. **请协助排查一个疑似适配器/运行时缺陷**:`@edgeone/opennextjs-pages` 的 `ComputeJsIncomingMessage` 把 `socket` 设为 getter-only,Next.js 在包装请求时对 `req.socket` 赋值会抛 `TypeError`。我们在 `/api/*` 路由上已实测到此问题并通过 middleware matcher 规避;但 SSR 页面路由(如 `/`)仍走 opennext 的请求包装,怀疑同样触发 → 每个请求必崩 → 502 且无应用日志。
4. **请确认一个构建侧回归**:`@edgeone/opennextjs-pages@0.2.4` 在 `output:'standalone'` + `outputFileTracingIncludes` 含静态资源(如 `prompts/**`)时,`onBuild` 钩子报 `ENOENT ... unlink .../ssr-node/prompts/vN/*.txt` → `No server-handler detected` → 退化纯静态。此问题在我们项目与另一同栈项目 `quote-check` 的**全新构建**上都能稳定复现(详见 §5)。
---
## 2. 项目技术背景
| 项 | 值 |
|---|---|
| 框架 | Next.js **16.2.4**(App Router,Turbopack 构建) |
| React | 19.0.0 |
| 运行时适配器 | `@edgeone/opennextjs-pages@0.2.4`(EdgeOne 自动注入) |
| 鉴权 | better-auth 0.7.5(Node runtime,proxy/middleware) |
| 数据库 | Drizzle ORM + Neon Postgres(@neondatabase/serverless,HTTP 驱动) |
| 对象存储 | 腾讯云 COS(@aws-sdk/client-s3,标记为 serverExternalPackages) |
| 异步任务 | Inngest(长任务校对,部署在 Railway,非 EdgeOne) |
| 包管理 | npm(`npm install --legacy-peer-deps`) |
**部署拓扑:**
- **EdgeOne Pages**:承载 Web UI / SSR(本工单问题所在)。
- **Railway**:运行同一个 Next.js 应用的 standalone 服务器(`node .next/standalone/server.js`),承载 Inngest worker 与长任务。
- Inngest Cloud:任务编排;Neon:数据库;COS:文件存储。
**EdgeOne Pages 项目「构建部署」配置:**
- 框架预设:`Next.js`
- 根目录:`./`
- 输出目录:`.next`
- 编译命令:`npm run build`(= `next build && npx tsx scripts/post-build-edgeone.ts`)
- 安装命令:`npm install --legacy-peer-deps`
- 构建 Node 版本(edgeone.json `nodeVersion`):先后试过 `22.11.0` 与 `20.18.0`
- `edgeone.json` 含 `cloudFunctions.nodejs.maxDuration = 120`
---
## 3. 现象(当前状态)
- Pages 构建**成功**(构建日志见 §6),Cloud Function(ssr-node)**部署成功**("Deploying functions completed",函数 bundle 约 905 KB)。
- 访问 `https://heimaojiaodui.com/`(以及任意路径,含静态首页 `/`):
```
502: CLOUD_FUNCTION_INVOCATION_FAILED
(Code: CLOUD_FUNCTION_INVOCATION_FAILED)
Cloud Functions call failed.
```
响应头 `Server: edgeone-pages`。
- **控制台「日志分析」无任何日志**(任何时间范围 / 环境 / 级别)。
---
## 4. 关键对照证据(强烈建议 EdgeOne 工程师关注)
### 4.1 同一构建在普通 Node 容器(Railway)完全正常
完全相同的代码、相同的 `output:'standalone'` 构建产物,部署到 Railway(标准 Node 容器,`node .next/standalone/server.js`):
```
GET https://ai-proofreading-production.up.railway.app/ → 200(正常渲染首页)
GET https://ai-proofreading-production.up.railway.app/login → 200
GET https://ai-proofreading-production.up.railway.app/api/inngest → 401(预期,签名校验)
```
➡️ **应用代码与构建产物本身正确无误,问题特定于 EdgeOne Cloud Functions 运行时的函数调用。**
### 4.2 本地复现 EdgeOne 构建产物亦正常
使用 `edgeone pages build` 在本地生成 `.edgeone/cloud-functions/ssr-node/`,直接运行其入口:
```bash
node .edgeone/cloud-functions/ssr-node/index.mjs # 监听 localhost:9000
curl http://localhost:9000/ # → HTTP 200,正常返回首页 HTML
```
➡️ opennext 产出的 handler 在标准 Node 下能正确处理请求并返回 200。**EdgeOne 运行时调用同一 handler 却 502。**
### 4.3 quote-check 对照实验(强证据:平台回归,非项目代码问题)
`quote-check` 是 `ai-proofreading` 的 fork 来源,**技术栈完全相同**(Next.js 16.2.4 + `@edgeone/opennextjs-pages@0.2.4` + better-auth + Drizzle/Neon + COS + Railway 上的 Inngest),同样部署在 EdgeOne Pages,框架预设 Next.js、`output:'standalone'`。它构成一个干净的对照组:
| 维度 | 结果 |
|---|---|
| quote-check **线上当前运行** | ✅ 正常 |
| 其生产部署的构建时间 / 提交 | **2026-05-19**(commit `c2270db`,branch `master`)——早于本回归约 18 天 |
| quote-check **今日(2026-06-07)触发重新部署**(commit `711d365`) | ❌ **报与本项目完全相同的 onBuild ENOENT**:`Error executing onBuild hook: ENOENT ... unlink .../ssr-node/prompts/v1/extract.txt` → `No server-handler detected` → `Build error` |
| quote-check **本地 `edgeone pages build`** | ❌ 同样复现该 ENOENT |
**结论:**
1. 该 `onBuild` ENOENT 是 **2026-05-19 之后引入的平台 / 适配器回归**——quote-check 线上之所以正常,纯粹因为它跑的是回归前(05-19)的旧构建产物;今天对它重新构建**同样失败**。
2. 此缺陷与各项目业务代码无关——两个独立项目的**全新构建**都稳定复现同一错误。
3. "对齐 quote-check 的可用配置"不可行:quote-check 05-19 能成功的那套配置,**今天在 EdgeOne 上同样构建不出来**。
➡️ **请 EdgeOne 重点核查 `@edgeone/opennextjs-pages` 在 2026-05-19 ~ 2026-06-07 之间的版本变更**(尤其 `onBuild` 钩子对 `output:'standalone'` + `outputFileTracingIncludes` 资源文件的 `unlink` / 去重逻辑)——两个项目、全新构建、同一错误、可定位的版本窗口,这是定位回归的最短路径。
---
## 5. 我们已尝试的排查与修复(按时间)
| # | 假设 / 操作 | 结果 |
|---|---|---|
| 1 | 框架预设原为 `other` → `.next` 被当静态托管 → 全站 404。改为 `Next.js` | 适配器开始介入;进入构建/适配阶段 |
| 2 | 删除导致 NFT 全量 trace 的 debug 路由 `app/api/debug/env/route.ts`(动态 `process.cwd()` 路径);修正 `book-profiles.ts` 为静态作用域路径 | NFT over-trace 警告消除 |
| 3 | `onBuild` 报 `ENOENT ... unlink .../ssr-node/prompts/vN/*.txt` → `No server-handler detected` → 退化纯静态。**在本项目与 quote-check 全新构建都复现** | 见 §5.1 |
| 4 | 用 `outputFileTracingExcludes` 把 `prompts/**`、`data/**` 移出 NFT 清单(绕开 onBuild 的 unlink) | **构建转为成功**,server-handler 正常生成,函数部署成功 |
| 5 | 但运行时仍 **502 且零日志** | 进入运行时问题排查 |
| 6 | 将 `lib/auth.ts` 的 betterAuth 单例改为惰性初始化(排除模块加载期抛错拖垮函数) | 502 仍在 |
| 7 | 精简 bundle:排除未使用的 sharp(16MB)+ 去重哈希别名,59MB→36MB(远低于 128MB 上限) | 502 仍在(故排除"体积超限") |
| 8 | 构建 Node 版本 `22.11.0` → `20.18.0`,对齐文档所述运行时 `v20.x`(怀疑原生模块 ABI / NODE_MODULE_VERSION 不匹配) | **502 仍在**(构建日志确认已切到 v20.18.0) |
### 5.1 onBuild ENOENT 回归(疑似 @edgeone/opennextjs-pages 缺陷)
`output:'standalone'` + `outputFileTracingIncludes` 含 `./prompts/**` 时,构建末尾稳定报:
```
[plugins][✘] Error executing onBuild hook: ENOENT: no such file or directory,
unlink '.../.edgeone/cloud-functions/ssr-node/prompts/v1/extract.txt'
...
[cli] No server-handler detected, generating routes.json for pure project...
Build error
```
- 在本项目 `ai-proofreading` 与同栈项目 `quote-check` 的**重新构建**上都稳定复现。
- `quote-check` 线上之所以正常,是因为其当前生产部署是 **2026-05-19** 的旧构建(在该回归引入之前);今日对其触发重新部署**同样报上述 ENOENT**。
- 推测:opennext 的 `onBuild` 去重/symlink 逻辑会对**进入 NFT trace 清单**的文件执行 `unlink`,对 `prompts/*.txt` 撞空 → ENOENT。我们的规避方法是将这些资源移出 NFT(`outputFileTracingExcludes`);由于 opennext `app.json` 的 `includedFiles:["**"]` 仍会整目录拷入 ssr-node,文件运行时依然存在,但 onBuild 不再对其 unlink,构建得以通过。
- **此项仅供 EdgeOne 改进适配器参考;它已被我们规避,不是当前 502 的直接原因。**
---
## 6. 最近一次成功构建 + 失败运行的日志(节选)
构建(commit `67c16f5`,Node 20.18.0):
```
Now, we're on node version v20.18.0 (npm 10.9.0)
> next build && npx tsx scripts/post-build-edgeone.ts
▲ Next.js 16.2.4 (Turbopack)
✓ Compiled successfully in 15.0s
✓ Finished TypeScript in 17.3s
✓ Generating static pages using 4 workers (35/35)
Route (app)
┌ ○ / (静态预渲染)
├ ƒ /api/auth/[...all] (动态)
...
ƒ Proxy (Middleware)
[opennext] Generated .../.edgeone/cloud-functions/ssr-node/config.json with 57 routes
[opennext] Restored original next.config
Build completed
...
Deploying functions
Functions completed: 39735ms
部署 完成 49s
```
运行(访问任意路径):
```
502 CLOUD_FUNCTION_INVOCATION_FAILED (控制台日志分析:空)
```
> 注:构建期出现 AWS SDK 的 `NodeVersionSupportWarning`(v3 在 2027 年后将要求 node>=22,当前 v20.18.0),仅为告警,不影响构建。
---
## 7. 怀疑根因(供 EdgeOne 工程师参考)
综合"本地 / Railway 同产物 200、EdgeOne 调用即 502、零日志、崩在应用日志之前",我们最强的怀疑是:
> **EdgeOne Cloud Functions 运行时的请求对象 `ComputeJsIncomingMessage` 将 `socket` 定义为 getter-only;opennext 的 SSR 请求包装(或 Next.js 内部)对 `req.socket` 赋值时抛 `TypeError`,导致每个请求在进入路由处理前即崩溃。**
依据:本项目 `proxy.ts`(Next 16 middleware)中已有注释记录——我们曾在 `/api/*` 路由上实测到该问题("`req.socket = …` 赋值触发 TypeError 500"),并通过 middleware matcher 排除 `/api/*` 规避。但 SSR 页面路由(如 `/`)仍会经过 opennext 的请求包装,怀疑触发同一缺陷。
请 EdgeOne 协助确认该假设,并指引修复或规避方式。
---
## 8. 请求 EdgeOne 提供 / 排查的清单
1. **运行时日志获取方式**:如何拿到该 Cloud Function 的运行时崩溃堆栈 / stderr(控制台日志分析为空)。
2. **运行时环境**:精确 Node.js 版本、架构、libc、内存上限、冷启动超时。
3. **从服务端排查**本项目 `ai-proofreading` 最近一次部署(commit `67c16f5`)的 ssr-node 函数调用失败原因。
4. **确认 §7 的 `ComputeJsIncomingMessage` / `req.socket` getter-only 假设**,及对 opennext SSR 路由的影响与修复。
5. **确认 §5.1 的 onBuild ENOENT 回归**(`@edgeone/opennextjs-pages@0.2.4`,standalone + tracingIncludes 资源),评估修复。
---
## 9. 供查证的标识(请按实际补全)
- EdgeOne 站点 ID / 域名:`heimaojiaodui.com`
- Pages 项目名 / ID:`ai-proofreading` / `pages-<请补全>`
- 失败部署 ID 与时间:commit `67c16f5`,部署时间约 2026-06-07 00:06–00:08
- GitHub 仓库:`WangYuBo/AI-Proofreading`(main 分支,Git 集成)
- 对照(正常):`https://ai-proofreading-production.up.railway.app/`(同构建在 Railway 正常)
---
*报告生成时间:2026-06-07*
相似问题