2025年8月13日 星期三

WordBank 開發經驗

Firebase 應用程式除錯全紀錄:從 400 錯誤到成功上線的實戰指南

在現代網頁應用程式開發中,與 Firebase 這類後端即服務 (Backend as a Service, BaaS) 平台進行互動是常見的架構。然而,從開發到上線的過程中,遭遇各式各樣的 API 錯誤幾乎是必然的。關鍵並非完全避免錯誤,而在於如何建立一套系統性的分析方法,精準定位問題根源,並逐步修正。

本文將詳細記錄一個真實案例——「英文單字學習板」應用程式,如何從一個看似簡單的 400 錯誤開始,經歷一連串層層遞進的偵錯挑戰,最終不僅解決了問題,更強化了應用程式的穩健性。

第一階段:根本性設定錯誤 — 400 Bad Request

  • 問題現象: 應用程式啟動後,畫面持續停留在讀取動畫,無法進入主功能。瀏覽器開發者工具 (F12) 的主控台 (Console) 顯示了兩項關鍵錯誤:

    1. 一個紅色的網路請求錯誤:POST ... 400 (Bad Request)

    2. 一則應用程式自訂的錯誤提示:「登入/建立帳號失敗!請務必前往 Firebase 控制台,啟用『電子郵件/密碼』登入。」

  • 問題分析與補充知識: HTTP 400 Bad Request 是一個標準的客戶端錯誤狀態碼,它意味著伺服器因為某些原因(例如語法錯誤、無效的請求訊息框架或欺騙性的請求路由)而無法或不願處理該請求。在此情境中,它表示我們的應用程式發送了一個 Firebase 後端無法理解或接受的請求。

    結合自訂的錯誤訊息,問題指向非常明確:應用程式的程式碼試圖透過 Firebase Authentication 服務的「電子郵件/密碼」供應商來驗證一個共用帳號,但該專案的後台並未開啟此驗證方法。因此,Firebase 伺服器從根本上拒絕了這個不被允許的請求類型,回傳了 400 錯誤。

  • 解決方案: 此為一次性的基礎設定,是使用 Firebase Authentication 的前置必要步驟。

    1. 前往 Firebase 控制台

    2. 在您的專案中,導航至 Authentication > 登入方式 (Sign-in method) 頁籤。

    3. 在登入供應商列表中,找到並**啟用「電子郵件/密碼」**選項。

第二階段:連鎖反應與安全機制 — auth/too-many-requests

  • 問題現象: 完成第一階段的設定後,滿心以為問題已解決,但應用程式依然卡在讀取畫面。開發者工具中的錯誤訊息轉變為 Firebase 特有的錯誤碼:auth/too-many-requests

  • 問題分析與補充知識: 此錯誤是典型的「連鎖反應」所致。在第一階段問題未解決時,開發者可能進行了多次重新整理頁面或重試操作。每一次失敗的嘗試都被 Firebase Authentication 記錄下來。

    auth/too-many-requests 是 Firebase 為防止暴力破解 (Brute-force) 攻擊而設計的標準安全機制,稱為**「請求速率限制」(Rate Limiting)**。當來自單一 IP 位址的登入或註冊請求在短時間內失敗次數過多時,Firebase 會暫時封鎖該 IP 的所有同類型請求,以保護用戶帳號安全。因此,即便我們已修正了後台設定,新的、本應成功的請求也被這個臨時的安全機制阻擋了。

  • 解決方案: 面對速率限制,唯一的解決方案就是耐心等待

    1. 立即停止所有相關操作,關閉應用程式分頁,避免產生更多請求。

    2. 等待數分鐘至一小時不等,讓 Firebase 的 IP 封鎖自動解除。

第三階段:憑證狀態不一致 — auth/invalid-credential

  • 問題現象: 在耐心等待,確認 IP 封鎖解除後,錯誤訊息再次演變,主控台顯示新的錯誤碼:auth/invalid-credential

  • 問題分析與補充知識: 這個錯誤碼的出現,本身就是一個好消息,它代表:

    • IP 速率限制已解除,我們的請求已能成功送達 Firebase 伺服器。

    • Firebase Authentication 服務已正常處理我們的請求,並對提交的憑證進行了驗證。

    auth/invalid-credential 的字面意思是「無效的憑證」。這通常表示提交的電子郵件或密碼組合不正確。然而,在我們的案例中,它揭示了一個更深層次的狀態不一致問題:程式碼嘗試登入的帳號 (shared.user@wordbank-app.com) 可能在之前的測試中建立過,但後來被手動從 Firebase 控制台刪除或停用。當程式碼再次使用這個「歷史上存在過但現已失效」的憑證登入時,Firebase 便會回傳此錯誤。

    補充說明: 值得注意的是,auth/invalid-credentialauth/user-not-found 存在細微但關鍵的區別。後者表示該電子郵件從未註冊過;而前者則暗示該帳號可能曾經存在,或提供的密碼有誤。

  • 解決方案: 為了一勞永逸地解決此問題,我們採取了「清理環境」與「強化程式碼」的雙重策略:

    1. 手動清理環境: 前往 Firebase 控制台的 Authentication 頁面,手動刪除任何可能處於損壞或狀態不明的 shared.user@wordbank-app.com 帳號,確保後端處於一個乾淨的初始狀態。

    2. 強化程式碼韌性: 優化登入邏輯,讓程式在接收到 auth/invalid-credential 錯誤時,能夠採取與 auth/user-not-found 相同的處理方式——自動觸發建立新帳號的流程。這使得應用程式具備了某種程度的自我修復能力。

核心實踐:提升應用程式穩健性的程式碼優化

在解決上述主要錯誤的過程中,我們同步進行了多項程式碼層面的優化,這些是開發高品質應用程式的關鍵實踐:

  • ▪︎ 精確的錯誤日誌與監控: 修改程式碼,確保在捕獲到任何來自 Firebase 的錯誤時,都能在主控台完整印出其原始的 error.codeerror.message。若沒有這些精確的錯誤碼,後續的除錯將寸步難行。

  • ▪︎ 完善的狀態管理: 重構了管理讀取狀態 (e.g., isLoading) 的邏輯。確保只有在所有關鍵的非同步操作(例如:使用者身份驗證、用戶學習資料載入)都明確完成或失敗後,才解除載入畫面,避免使用者看到不完整的介面。

  • ▪︎ 優雅處理邊界情況 (Edge Cases): 新增了對「使用者已登入,但尚未建立任何學習者設定檔」這一邊界情況的處理。應用程式現在會顯示一個引導畫面,邀請使用者建立第一個學習者,而不是卡在空白或無響應的狀態。

總結與核心心得

這次的除錯歷程是一個絕佳的實戰範例,它提煉出以下四點核心開發心法:

  1. 錯誤日誌是除錯的生命線: 脫離猜測,依賴精確、詳細的錯誤日誌是最高效的除錯手段。

  2. 系統性分析,逐層剝離問題: 複雜的問題往往是多個簡單問題的疊加。解決一個問題後,下一個潛藏的問題才會浮現。保持耐心,系統性地分析是關鍵。

  3. 深入理解後端服務的內建機制: 了解並尊重您所使用的後端服務(如 Firebase)的內建安全策略與運作原理(如速率限制),能幫助您快速理解問題並找到正確的解決方向。

  4. 打造具備「韌性」的應用程式: 編寫能夠預期並優雅處理可預見錯誤(如帳號被手動刪除)的程式碼,使其具備自我修復或清晰引導的能力,是區分普通與優秀應用程式的重要標誌。

2025年8月5日 星期二

猜數字遊戲

猜數字遊戲

我已經想好了一個 1 到 100 之間的數字。

 

已猜次數:0

2015年10月6日 星期二

[西雅圖][美食] 好香好酥好多吃好好吃的卜派炸雞


今天因為來機場還車租車
弄完剛好一點了
只好就近找有名的餐廳了
於是來到405高速公路2號出口不遠處的卜派炸雞

決定要來吃的同事把這間炸雞形容的很厲害
說什麼又大又酥又香
聽起來好像不吃不行一樣
於是就來了


店家門面跟裝潢其實我覺得還不錯
清爽寬敞比其他的速食店好多了


店裡面也有擺設一些他們所使用的香料
看起來就很香
只是說在沒吃到以前
還是不能輕下斷言阿



等了大概五分鐘
終於輪到我們的餐了
我們點了炸鯰魚跟炸雞


美國的炸鯰魚其實很普遍
我不知道是不是很受歡迎
但是我跟同事是滿愛吃的
有時候去超市也會買個幾片請店員幫忙炸
卜派炸雞的炸魚不同的是
有淡淡的香料味
吃起來酥脆之外  又不會太膩的感覺
這邊的魚肉炸的也不會太乾  至然保有魚肉多汁的特性
推一個


當然炸魚只是開胃菜
重點是拳頭大的炸雞阿
鄉親啊
尼侃侃  尼侃侃  有夠大
就是差我們沒有人臉比例尺而已
下次應該出門帶個捲尺量大小XD
這個雞肉軟嫩外皮又脆
咬一口皮帶點肉   在口中充分咀嚼攪拌
有肉的甜味   也有外衣的口感
真的是一大享受
而大份量的炸雞們
自然也是吃得飽的
跟水牛城比起來就是比較有明顯的飽足感
整體而言
這次隨興的前往真的是賺到啦



2015年9月14日 星期一

[西雅圖][美食] 動動你的手指頭吧 好吃的水牛城炸雞


今天來到一家號稱很厲害的炸雞店
就是華盛頓的水牛城炸雞店

水牛城炸雞厲害的特點在醬料
這邊的醬料有分酸甜跟辣度
大家可以看下面這張圖中間
就是各種口味的分佈
上面比較酸
下面比較辣
大家可以按自己喜好
選擇不同的組合


一開始我們也不知道該從何點起
於是只好入境隨俗的聽服務生的推薦
印象中有甜的BBQ跟辣味BBQ
都超夠味的
而這邊的炸雞可能是為了裹腹醬汁  所以炸得比較乾
但我感覺吃起來肉是滿香的
加上各種美味的醬汁
吃起來就更加過癮

附帶一提的是
有附一些蔬菜棒
為了有一個好的消化
所以我先吃了一下蔬菜們
補充一下膳食纖維在開始吃炸雞喔





因為炸雞大家都是用手拿的
所以店家也有貼心準備濕紙巾來給用餐的客人擦手



另外水牛城的設計其實就是運動餐廳的感覺
裡面有大大小小的電視或是布幕
播放著各種運動賽事
我想有熱門比賽的時候
店裡肯定是非常的熱鬧吧XD


以下是店家資訊
店名:Buffalo Wild Wings
地址:18508 33rd Ave W Lynnwood, WA 98037
營業時間:
Mon-Sat: 11AM to 1AM  Sun: 11AM to 12AM 











2015年4月17日 星期五

[西雅圖][旅遊] 從Rizal park看夜景

今天晚上來到西雅圖的另外一個看夜景的地方Rizal Park
我喜歡這裡勝於Kerry park
四周空曠的角度可以一覽西雅圖市區跟棒球場
而站在橋上    還能俯瞰錯縱的高速公路與車流
只是橋上有點抖    特別是公車經過    震動更明顯
不過我想橋是很堅固的    可以放心拍照(抖~~~)

至於停車也頗為方便
是路邊停車    免費!!(眼睛為之一亮了~~~XD)

另外    推薦大家最好能夠自備外套看夜景
因為晚上會有點冷


我們到的時間點已經過了尖峰時刻
所以車流量不多


2015年4月15日 星期三

[西雅圖][旅遊] Pike market - 派克市場快速逛

為了避開人潮壅擠的時刻
這次我們特地選了Week day來逛逛晃晃買紀念品

派克市場的停車費比較貴一點
一小時是2.5元(是有沒那麼在意停車費XD)

第一站是逛傳統市場 + 吃生蠔
生蠔好吃~~可惜的是忘了拍個特寫已經咕嚕滑過喉嚨了


2015年4月14日 星期二

[西雅圖][旅遊] 來去Kirkland小鎮逛逛





今天來到Kirkland(柯克蘭)逛逛
如果常常光顧Costco    應該對這個名詞很有印象
是的    Kirkland就是Costco的發源地
我們今天來到的地方是鄰近湖邊的一個小鎮

我滿推薦來這邊走走晃晃     發發呆
這個城鎮充滿了一種奇妙的靜謐感
剛知道這個地方的時候
我跟同事三天兩就會到這邊走走
不一定要做什麼
但是到湖邊走走 就能暫時揮別工作的壓力