# 2026-05-13 cypher-executor outbound fetch 全失效(CF 同 zone 自循環死鎖) > **總耗時**:約一整天 debug > **根因**:Cloudflare Workers 對「綁 custom domain 的 Worker fetch 同 zone 另一個 custom domain Worker」會撞 zone routing 死鎖 → 回 522 > **修法**:cypher-executor fetch component worker 改走 `*.workers.dev` 子域(不同路由系統,繞過 zone proxy) > **影響**:mira 7B.3c 阻擋一整天;封測 P0 從「全綠」revert 成 #9 阻擋 --- ## 症狀 mira 跑 `acr run wiki_synthesis`(5 節點 workflow,含 kbdb_get / claude_api)回: ``` n1 → {"success": false, "status": 522, "error": "error code: 522"} ``` 每節點精準 ~1000ms timeout 後 522。 進一步測試發現**所有 outbound HTTP fetch from cypher-executor 都 522**,無論目標是: - 同 zone:`kbdb-get.arcrun.dev`、`claude-api.arcrun.dev`、`cypher.arcrun.dev/health`(self) - 外部:`httpbin.org`、`github.com`、`google.com` 但 **service binding 路徑(SVC_STRING_OPS 等 15 個邏輯零件)完全正常**。 ## 觀察矩陣 | 路徑 | 結果 | |---|---| | 本機 curl → kbdb-get.arcrun.dev | 200 ✓ | | cypher-executor → kbdb-get.arcrun.dev (HTTP fetch) | **522** | | cypher-executor → claude-api.arcrun.dev (HTTP fetch) | **522** | | cypher-executor → httpbin.org (HTTP fetch) | **522** | | cypher-executor → string_ops (Service Binding) | 200 ✓ | | `acr run hello`(純 SB 1 節點)| 200 ✓ | | `acr run`(5 節點純 SB chain,wallTime 2.2s)| 200 ✓ | | **wrangler dev(本機跑 cypher-executor)→ httpbin / kbdb-get** | **200 ✓** | | 同 src 部署成 `arcrun-cypher-executor-probe`(純 workers.dev,無 routes 綁定)→ httpbin / kbdb-get / claude-api | **200 ✓** | 最關鍵兩條: 1. **本機 wrangler dev 跑同 src,fetch 全通** → 不是 code bug,是 prod 環境問題 2. **probe worker(同 src、不同 name、走 workers.dev、無 cypher.arcrun.dev route)→ 全通** → 是 `cypher.arcrun.dev/*` route 觸發的環境問題 ## 誤判路徑(重要 — 避免重犯) | 假設 | 為什麼錯 | |---|---| | **A. CF Free Tier 10ms CPU cap**(首先猜的)| 5 節點 SB chain 跑 2.2 秒卻通過,CPU cap 假設立刻被推翻。但前期 debug 走了不少彎路 | | **B. 用戶從 Paid 掉到 Free** | 用戶確實掉到 Free,當下繳費恢復 Paid,**重測仍全 522**,徹底排除付費假設 | | **C. compatibility_date 太舊(2025-02-19)**| 沒嘗試 bump,但本機 dev 跟 prod 同個 compatibility_date 一通一不通,**不是這個** | | **D. 5/8-5/9 manual deploy 推了壞掉的 unpushed commits** | git diff 本機 vs origin/main 確實有 3 個 unpushed commits,但檢查 prod bundle 內 `makeHttpRunner` 跟本機 src 一字不差。**code 沒問題** | | **E. Bot Fight Mode / WAF 攔截 outbound fetch** | 用戶截圖 zone Security 設定,Bot Fight Mode 未開。**不是這個** | | **F. 帳號層 outbound network policy 限制** | dashboard worker bindings 完全乾淨(無 outbound worker / tail consumer / Hyperdrive 等),**不是這個** | | **G. CF Worker subrequest quota** | wrangler tail 顯示 `wallTime: 497ms, cpuTime: 2ms, outcome: ok` —— cypher-executor 自己沒撞任何 quota,是 fetch 出去就被攔 | | **H. u6u-mcp service trigger 攔截** | 那是 reverse direction(u6u-mcp 把 cypher-executor 當 service binding 呼叫),跟 outbound fetch 無關 | **共通教訓**:522 來自「fetch 出去就被攔截,cypher-executor 不知情把 522 包成 component output 回 client」。wrangler tail 看 cypher-executor outcome 是 `ok` —— **不要被 worker 自己的 `ok` 騙了**,要看 trace 內 component output 才是真相。 ## 真相 CF Workers 對「綁 custom domain Worker A 用 `fetch()` 打同 zone 另一個 custom domain Worker B」會撞 **zone reverse proxy 路由死鎖**。具體機制(推測): 1. cypher.arcrun.dev/* route 觸發 → cypher-executor 收到請求 2. cypher-executor 內部 `fetch("https://kbdb-get.arcrun.dev/")` 出去 3. CF edge 看「目標 hostname 是同 zone (`arcrun.dev`),有 worker route」 → 走 zone reverse proxy 4. 同 zone re-entry 觸發 CF 自循環防護 → fetch 不能完成 5. 對 cypher-executor 表現為「fetch 等到 timeout,得到一個假 522 response」 6. cypher-executor 不知情,把 522 當作 component 真實回應傳回 client httpbin.org 也 522 不是 same-zone 問題,可能是「進入 outbound fetch code path 就被同樣機制 abort」的副作用(這部分仍不完全清楚,但實證 workers.dev 路徑無此問題)。 **`*.workers.dev` 不走 zone reverse proxy**,是 CF 內部的另一條路由(worker-to-worker internal routing),不撞死鎖。**Service Binding 同理**(不走網路,process 內呼叫)。 ## 為什麼以前能跑 4/18 arcrun.md 記錄「httpbin_post 端對端驗證通過」,當時 cypher-executor 也是綁 cypher.arcrun.dev/*,也是 fetch *.arcrun.dev,**卻能通**。推測 CF 之後某次平台更新收緊了 same-zone fetch 防護,但確切時間不可考。 → **教訓**:CF 平台行為會悄悄變,依賴 `fetch(*.same-zone.dev)` 是脆弱設計,從此架構上不該再依賴。 ## 修法 **改 4 個檔案**(commit see git log around 2026-05-13): 1. `cypher-executor/src/lib/component-loader.ts`: - `wasmWorkerUrl(canonicalId, subdomain)` 簽名加 `subdomain` 參數 - URL pattern 從 `https://${kebab}.arcrun.dev` 改為 `https://arcrun-${kebab}.${subdomain}.workers.dev` - 兩個 caller(line 128 / line 192 fallback)同步改 2. `cypher-executor/src/actions/auth-dispatcher.ts`: - `wasmWorkerUrl(...)` 呼叫同步加 `subdomain` 參數,從 `env.WORKER_SUBDOMAIN` 取 3. `cypher-executor/src/types.ts`: - `Bindings` 加 `WORKER_SUBDOMAIN: string` 4. `cypher-executor/wrangler.toml`: - `[vars]` 加 `WORKER_SUBDOMAIN = "uncle6-me"` **Dashboard 一次性手動操作**:5 個 P0 component worker(kbdb-get / kbdb-ingest / kbdb-create-block / kbdb-patch-block / claude-api)→ Settings → Domains & Routes → workers.dev → **Enable** **未來新增 component worker 時必須**:dashboard 啟用 workers.dev URL(rule 03 已加入步驟 5) ## 驗證 修復後重測同樣 3 個 trigger: | Trigger | 修復前 | 修復後 | |---|---|---| | cypher → kbdb-get | 522 (1064ms) | **200 (2027ms)** 拿回真實 block 內容 | | cypher → claude-api | 522 (1014ms) | **200 (6226ms)** Claude 真實回應 | | cypher → httpbin | 522 (1023ms) | 404 error 1042(不是 522 死鎖了;外部 fetch 限制是另一個問題,不影響 mira)| mira `acr run wiki_synthesis` 5 節點 workflow 跑通前 3 節點(load_schema / load_skill / load_entities),後續節點失敗是 mira 業務邏輯問題(Unauthorized 在某個 block id),不是 cypher-executor 平台問題。 ## 影響範圍與善後 **影響**: - 任何用 cypher-executor 跑外部 fetch 的 workflow 都壞(封測 Step 2/5/6 / mira / 自架用戶) - arcrun 「每個零件 = 公開 URL」承諾在純 `*.arcrun.dev` 體系下無法跟「cypher-executor HTTP fetch」並存 **善後(已做)**: - ✅ rule 01-tech-stack.md:URL 慣例改為「對內 workers.dev / 對外 arcrun.dev」二元 - ✅ rule 03-component-architecture.md:第一核心概念改為「每個零件 = 兩個 URL」,部署步驟加 dashboard workers.dev enable - ✅ arcrun.md P0 #9 標 resolved 並 reference 本 incident - ✅ probe worker 已刪 - ⏳ mira tasks.md 7B.3c 解除阻擋(即將) ## 未來怎麼避免 1. **新 component worker 部署 checklist 強制包含 dashboard workers.dev enable**(rule 03 已加,但實務上靠 dashboard 容易忘,未來可考慮寫 deploy 後驗證 script) 2. **不要再加 outbound HTTP fetch 對同 zone hostname** —— cypher-executor 對任何 `*.arcrun.dev` 的 fetch 都該走 workers.dev URL 3. **wrangler dev 是診斷神器** —— 本機跑 prod 同份 src 是區分「環境問題 vs code 問題」最快方法,未來 prod 出怪異行為先跑這個 4. **wrangler tail outcome:ok 不代表沒問題** —— 要看 component trace output 才是真相 5. **Self-hosted fork 文件要明寫**:必須改 `WORKER_SUBDOMAIN` + 所有 component worker dashboard 啟用 workers.dev(rule 03 已加,BETA_TEST.md 待 onboarding 章節加) ## Reference - 對應 SDD:`matrix/arcrun/.agents/specs/arcrun/arcrun.md` P0 #9 - 規範更新:`matrix/arcrun/.claude/rules/01-tech-stack.md`、`rules/03-component-architecture.md` - 受影響 SDD:`polaris/mira/.agents/specs/mira-app/tasks.md` 7B.3c(阻擋一整天)