這週 3Q 團隊在跨專案的排查工作中,反覆遇到同一類問題:程式不報錯、健康檢查一切正常,但某條功能路徑已經悄悄失效。從發票配號跳兩萬碼、到訊息重送永遠漏掉同一種 endpoint、到二十四輪測試都過了才發現權限被反向代理擋掉——每個案例的根因都藏在正常監控視野以外。這份週報記錄四個值得細看的靜默失效案例,以及每個案例背後的修法取捨。
發票號碼跳兩萬碼:修了顯示,但行為吃的是同一個髒欄位 #
電子發票配號系統讀取資料庫的 current_number 作為下一張起點,但這個欄位在三週前的舊系統 DBF 匯入時已被污染——起號被加上了舊系統的累計值,造成配號跳兩萬多碼。更棘手的是,三週前曾發現此污染,但當時只修正了儀表板的「顯示」算法,沒意識到配號本身也吃同一個欄位,修了一半,洞留著。若污染值推過字軌迄號,系統判定字軌用完,POS、候位、第三方支付三條結帳路徑同時掛掉。
修法選擇「完全不信 current_number」:改以「該字軌實際已開出去的最大號 + 1」即時推算,並在每次配號時順帶把被污染的欄位校正回實際值,讓系統自我修復存量髒資料。這比「修正匯入時的寫入邏輯」更安全,因為後者只能防未來,無法處理已存在的舊髒資料。同批建立了不依賴 mock 的 e2e 驗收腳本,直接 import production 端的處理器逐一呼叫——第一次跑即抓到一個純 SQL 驗證看不到的新 bug:銷售統計的稅額計算在改寫時漏排除作廢發票,導致報表中心與銷售統計數字不一致。修正後 36 項全過。
「修了顯示但忘了行為也吃同一欄位」是資料污染問題的典型擴散模式。驗收腳本若走的是與前端按鈕相同的程式碼路徑,才能抓到純 SQL query 看不到的邏輯缺陷。任何需要和舊系統做資料對接的場景,都值得把「欄位語意是否被舊系統累計值污染」列為驗收必查項目。
九種 endpoint 支援了八種:服務重啟才會觸發的靜默遺漏 #
電子發票系統的 POS 端採「先即時送、失敗才進同步佇列」策略,佇列 worker 負責重送時依 endpoint 類型逐一分派。但即時路徑與重送路徑的支援清單是兩份獨立維護的——其中一種 endpoint(贈品扣量)從未被加入重送清單。系統長期穩定時不會觸發,因為即時呼叫成功就不會進佇列;觸發條件是後台服務短暫重啟:重啟期間的所有贈品呼叫即時失敗、進佇列,worker 重送時碰到未知 endpoint,重試五次後靜默標為 failed,從此不再重試。
eMobile 1.0.53 補上了缺失的 case,並重新比對確認全部九種 endpoint 均有對應處理。這次排查也讓一個設計層面的問題浮出水面:任何需要兩份清單保持同步的架構,都應該讓「清單不同步」在程式碼審查或 CI 時就能被發現——例如讓 outbox 分派成為「預設應涵蓋全部即時路徑」的受控清單,或加入覆蓋率驗證,而不是靠開發者手動記得兩邊同步更新。
靜默失效最難找的原因,往往不是邏輯錯誤,而是「有一條路徑的覆蓋率在設計上就不完整」。任何需要兩份清單保持鏡像的系統,觸發條件越罕見(如服務中斷),缺口就越晚被發現、損失也越難追回。
二十四輪測試都過了,問題出在應用程式以外的 HTTP 標頭 #
某客戶的交付系統在內網測試期間,司機定位、掃碼等功能全程正常。直到第二十四輪追查「定位資料零筆」,才發現問題:走正式網址的真實使用者,瀏覽器靜默拒絕地理位置與相機權限,頁面上沒有任何錯誤提示,功能就這樣安靜地失效。前二十三輪測試全程走內網直打,這一整類問題(反向代理注入、CDN 規則)從未被觸發。
追查到某台反向代理伺服器全域注入了瀏覽器權限控制標頭,空白名單代表連同源請求都被禁止。修法選擇只在該站點的 vhost 覆寫,其餘站點保持原有設定,並以四層驗證交叉確認:標頭回傳值、其他站點未受影響、既有安全標頭完整保留、瀏覽器實測定位與相機均正常取得。同批沿同一條路徑往下查,發現框架預設的上傳大小限制遠低於手機直拍照片,補上前端壓縮後兩個問題一起解決,且對行動網路用戶更友善。
驗收測試若全程走內網,有一整類問題不會被觸發。交付驗收流程應包含至少一輪走正式網址、在真實設備上執行的端到端測試,才能覆蓋到應用程式程式碼以外的環境差異。
一個欄位是空的,三條功能路徑同時靜默停擺 #
量化交易系統中,某支持倉的進場計畫是以手動方式建立,繞過了系統標準 API 的寫入流程,導致策略組合欄位未被填入。結果不是立即報錯,而是三個看似獨立的症狀同時出現:K 線標頭的進場鎖定圖示消失、Phase 2 出場策略整條邏輯不執行、自動條件單缺失。這支持倉因此只剩停損保護,而無策略出場——在訊號來臨時系統不會反應,卻不會有任何錯誤訊息。
排查時逐一追溯三條路徑的執行鏈,確認三個症狀共指同一根源後,修復分三層:修改 API 寫入時自動查詢並填入策略組合,確保未來手動建立的計畫不再踩同樣的坑;以兩個獨立資料來源互相印證後回填歷史資料(可追溯、非任意指定);補建條件單格式與其他持倉完全對齊。驗證時逐一確認三條路徑均恢復正常運作。
手動操作繞過系統建立流程,產生的通常不是功能損壞,而是資料結構不完整——不報錯,只在後續邏輯中靜默失效。一個缺欄位往往同時斷掉多條依賴它的路徑,排查時必須逐條追溯,而非假設所有症狀來自同一機制。
本週其他進展 #
- Claude Nexus 補接 Gemini 後端,不動現有 Claude 路徑 — Chat 頁模型選單的 Gemini 選項補上實際執行路徑,偵測到 gemini-* 模型時繞開 Anthropic SDK 改走內部 claude-proxy 鏈,多輪對話脈絡以拼接歷史方式維持。Claude 原有路徑一行未動,零風險上線。
- Claude Nexus 模型選擇改為瀏覽器端記憶,不同專案互不干擾 — 前端以 localStorage 按專案路徑為 key 各自記憶上次選擇的模型,下次開頁自動恢復,不同專案的偏好互不影響,無需後端 session 化。
- Solar Monitor 修復資料收集主迴圈死鎖,確認電壓根因 — 排除電表切換的兩個隱患:None 回應被誤判成功、get_status() 在持鎖期間重入觸發死鎖。驗證 eval_count 每分鐘持續累加後確認修復。另完整排除軟體與電池因素,確認市電 L2 相電壓過低為逆變器拒絕並聯的根本原因,轉現場電工跟進硬體。
- Solar Monitor 修復儀表板時區查詢 bug,減少一次 DB 請求 — 前端以 UTC 查詢、資料庫存台北時間,造成取到 8 小時前舊值覆蓋即時資料。改直接使用 latest API 已有的即時欄位,消除多餘的時區錯位查詢。
- 3Q夥計 FTP 上傳改為格式白名單過濾,補傳範圍固定不漂移 — 從排除特定檔名改為嚴格白名單(年月日_時間格式),系統縮圖與無關檔案在格式驗證關被擋。補傳起點固定為開機日期,搭配進度紀錄去重,三種情境實測均通過。
- 3Q夥計 車機 YOLO 推論規格基線建立,固化進標註指示文件 — 實機確認輸入解析度、CPU 推論限制、熱保護降頻行為,並將所有硬體約束條件寫死進標註指示文件,確保後續訓練規格不會產出與車機部署條件不符的設定。
- sunnypilot 雷達接入完成,跟車幀配對率達 86.8% — 在不修改上游任何檔案的前提下,透過獨立 DBC 定義修正 platform flag,讓雷達介面自行開第二個解析器。實際 log 驗證顯示雷達距離配對顯著優於純視覺估算,未來 rebase 不帶入衝突。
- gomylife 上線旅宿消費登錄抽獎案例頁 — 新增客戶案例頁,技術主軸為六層獨立發票真偽檢核,繞開官方 API 資安門檻,每層單獨記錄結果供後台人工審查,定性為案例而非產品。
- gomylife eMobile B2B 產品頁描述升級,聚焦收銀機式開票模組 — 改版前描述停在 UI 框架升級,改為精準說明「B2B 為主偶有散客」場景下,加購模組後 B2B 與 B2C 共用同一組字軌、無需另外申請的具體價值。
- gomylife 內容雷達補充讀取範圍,消除重複建議問題 — 額外讀入案例清單與各產品頁已寫過的小節清單,並把分類準則直接寫進 prompt。雷達建議從「重複提醒已完成工作」改為「確認現有內容是否仍準確」。
- YISEN 憑證排版自動縮放,全庫發票交叉驗證無一溢出 — 蓋章欄字級從固定值改為從大往小自動遞減至排得下為止,確保賣方名稱完整可見。以全庫發票跨三種紙張交叉驗證後確認無溢出。
- YISEN 新增 A5 直式與橫式紙張支援,附用紙建議進操作手冊 — 實測 A5 直式較 A4 用紙節省一半且頁數差距小,列為推薦選項;A5 橫式因明細欄行數少分頁增多,列為非必要不選,兩項建議直接寫入操作手冊。
- YISEN 折讓單功能從無到有建立,v0.7.13 上線 — 新增折讓明細頁(支援篩選、排序、依篩選產憑證)、進銷分離存放,媒體申報檔扣抵別逐位元驗證,並處理 CSV 格式定址與手動匯入路徑的邊界問題。
- YISEN 請款單隱性資料遺失修復,列高動態分配 — 加減項欄位原有硬編碼兩個位置的 FoxPro 遺留設計,第三筆以後照算不印,造成帳面對不上。改為有幾筆印幾列,超過五筆合併顯示,表格總高鎖定不超一頁。
- PiBar 樹莓派硬體規格基線確認,進入應用開發階段 — 透過 SSH 遠端確認主機型號、記憶體容量、螢幕型號與旋轉設定、觸控裝置識別均正常。記憶體為官方最低款,已識別為未來同時跑多服務時的首要瓶頸,需從架構層面預先規劃。
- 某門市客戶 拍貼機每日實際拍照人次統計 pipeline 上線 — 排程讀取當日照片後逐張以 AI 計算人數寫入資料庫,另一支排程讀取已算好的數字生成日報,並建立代幣發放數與實際拍照次數並排顯示的後台頁面。
- 某門市客戶 促銷活動自動到期,查詢端補日期條件 — 前台與結帳雙路徑均未套用 startDate/endDate,活動只能靠人工關閉。修法在查詢端補日期條件(null 視為無限期),任何設好結束日的活動從此自動失效,不再需要人工收尾。
- 某客戶交付系統贈品報表時間與金額顯示修正 — 贈品寫入當下訂單尚未同步導致金額顯示空白、時間顯示寫入時間而非發票時間。改為用發票號碼反查訂單,以發票開立時間為準,找不到才退回寫入時間。
- invoice lottery 慢旅北投抽獎系統版型全站對齊完成 — 補齊「活動好禮」與「得獎公告」兩區塊的標題字級、eyebrow 樣式、卡片結構,對齊全站統一語彙;修復首屏滿版輪播因 mouseover 觸發區過大導致永遠暫停的 bug;reCAPTCHA 新網域驗證通過,確認正式流量正常。
- invoice lottery 驗收確認單全面重寫,補建驗收專用帳號 — 原驗收單網址、帳密、操作路徑全部過期,客戶照著做第一步就失敗。另建與管理員帳號隔離的驗收專用帳號,並明確列出上線前三件待辦事項的執行時機。
- gomylife 9 個產品頁 SEO 收錄狀態確認 — 透過 Google Search Console 逐頁核對,9 頁全數已索引,HTTPS 與結構化資料均為有效狀態,確立 sitemap 更新後無需手動提交即可收錄的可複用驗收 SOP。
- 倉儲照片插檔作業完成,生成 9 頁查驗文檔 — 15 張照片改名後傳至伺服器,以 python-docx 自動插入 Word 檔案,生成完整查驗照片文檔,待最終確認。
- planmaker 廣告活動全程執行收尾,CTR 於開賣日起明顯提升 — 完成為期十二天廣告活動的全程監控與核銷文件整理,開賣後 CTR 顯著優於預熱期,驗證廣告策略與活動時間點對齊準確。以正式發票 PDF 為核銷依據,避免中間計費數字被反覆質疑。
本週技術心得 #
這週橫跨多個專案的工作,讓我們反覆思考一個共同問題:為什麼有些 bug 在系統運行順暢時完全隱形,只在邊緣條件下才浮現?
觀察下來,靜默失效通常有幾個共同結構:一是「覆蓋率不對稱」——即時路徑與重送路徑、顯示邏輯與行為邏輯,各自維護一份清單,任一方新增時沒有機制強制同步另一方;二是「假設傳遞性」——欄位 A 被修了顯示,就假設行為也修了,但行為讀的是同一個欄位的不同副本;三是「測試路徑不完整」——走內網的測試永遠觸發不到反向代理注入的問題,走 mock 的測試觸發不到 production handler 的邏輯缺陷。
對中小企業的 IT 系統而言,這類問題的危險在於它不會立即報警,只在特定條件下(服務重啟、走正式網址、手動建立資料)才觸發,而此時問題往往已累積了一段時間。比起找到它,更值得投資的是讓它「不可能發生」:讓兩份清單的差異在 CI 時就可見、讓配號邏輯不依賴可被污染的欄位、讓驗收流程有一輪強制走正式環境。預防的成本遠低於靜默失效在正式使用者身上被發現的成本。
本文是 3Q 工程團隊的每週技術進度整理,由 Claude 協助編寫。內容聚焦技術類型與通用心得,不含客戶資訊。
