AI寫程式的 10 個坑:Claude Code 實戰防呆清單

重點摘要

AI寫程式最怕的不是寫錯,是寫錯了還回報成功:檢查全綠、退出碼 0,檔案卻是空的。我們用 Claude Code 這類 AI 代理寫程式、做網站,整理出 10 個實際踩過的坑與防呆:先跑正反對照組、守門用退出碼擋、驗收看產物本身。

AI寫程式(讓 AI 代理替你寫、改、執行程式)最常出事的地方,不是程式寫錯,而是寫錯之後沒有任何訊號:檢查程式報綠燈、指令回傳 0、代理說「完成了」,產物卻是空的或壞的。防呆的做法很固定:每把檢查先跑「一定該中」和「一定不該中」兩組對照、上線前的守門一律用退出碼擋下部署、驗收時看產物本身,不看有沒有報錯。

這些經驗來自我們 2026 年 8 月到 10 月用 Claude Code 寫自動化程式、建靜態網站、維護雲端排程的實際紀錄。能重現的幾個,我們 2026 年 10 月 23 日用 Python 3.10 重跑過一次。

AI寫程式最常出事的是哪裡?

AI 寫程式出事,多半不是語法錯誤,因為語法錯誤會當場噴錯、代理自己就會修。真正危險的是四種「沒有訊號」的失敗:結果錯了但沒報錯、檢查程式本身壞了所以一直綠燈、程式根本沒跑卻回傳成功、守門擋了但後面的步驟照樣執行。這四種都會讓代理和人同時以為「做完了」,等到使用者回報才發現。

失敗型態 長什麼樣 例子 怎麼抓
靜默算錯 沒有錯誤訊息,結果是錯的 正規式永遠不命中、表單把客人名字切斷 每把檢查先跑正反對照組
假綠燈 測試全部通過,功能其實是壞的 白名單把合法檔名全部擋掉,API 層 22 項測試全綠 拿已知合法與已知不合法的樣本各跑一次
沒跑卻回 0 退出碼 0,產物沒有更新 背景執行被提早收掉,137 頁一頁都沒掃 看產物:結束那一行、修改時間、內容時間戳
擋了沒擋住 檢查回報失敗,下一步照樣執行 Claude Code hook 回傳 1,工具呼叫照樣執行(官方文件寫明) 擋下時明確回傳 2,再做一次負面測試

四種的共同點是:代理回報的「成功」來自過程(有沒有報錯、退出碼多少),不是來自結果。所以驗收的主詞要換成產物:檔案大小、內容、筆數、線上頁面,這幾樣對了才算完成。

實測數據表:每個坑量到的數字與條件

項目 做法 結果 條件、日期、樣本數
指令裡的反斜線 透過代理的 Bash 工具送出含 \\b 的 Python 指令 到 Python 手上變成退格字元,正規式永遠不命中、不報錯 Windows 環境,2026-09-17
覆寫檔案 open(path, "w") 後 write 拋例外 檔案變成空的,舊內容沒了、新內容也沒寫進去 2026-09-21,1 次事故;10-23 重跑重現
Windows 換行 文字模式寫 JSON 只加 11 行,diff 顯示 135 行全改 2026-09-24
字元白名單 「每個字都是 16 進位」加「結尾是 .webp」 合法檔名全部被拒,API 層 22 項測試全綠也沒抓到 2026-08-26,1 個後台
正規式字元類 把欄位標籤詞放進 [^...] 15 個單字被排除在值之外,名字含這些字的客人被切斷 2026-08-30,表單解析
背景執行 背景執行再加 nohup … & 只印 2 行就回 0,137 頁一頁都沒掃 2026-09-20
遠端執行腳本 把 base64 腳本用管線交給 sudo bash 腳本內容被 ffmpeg、apt 讀走,後段指令沒照預期執行 雲端主機,2026-10
設定檔追加 結尾沒換行的 .env 用 echo 追加 新設定黏在上一行,兩個設定一起壞 2026-10
看畫面下結論 代理只看渲染後的頁面 回報「沒有公開條款」,API 裡其實有 12 檔、合計 15,658 字 2026-09-22,1 個網站
軟失敗步驟 抓資料失敗只寫 log、不中止 不告警,網頁停在舊資料 2026-09-20
健康檢查路徑 在 Git Bash 下用 gcloud 建監控 /health 被改寫成 /C:/Program Files/Git/health,從建立起就 404 2026-09-10
規則存放方式 規則散在 20 個筆記檔 同一天漏了 5 件事;改成 Skill 加守門後,上線當天擋下我們自己的作品兩次 2026-09-21
平行代理 一次派 5 個代理做稽核 每個約吃 20~30 萬 token,撞到每週用量上限 2026-09
本機壓測 Windows 一次開約 240 條新連線 被系統拒絕,改成同時 150 條 2026-10

踩過的坑:現象、原因、怎麼修

坑一:反斜線被吃掉,正規式永遠不命中

現象:代理寫了一段 re.search("\\bcat\\b", s) 的 Python 指令直接執行,不管字串裡有沒有 cat 都回「找不到」,也沒有任何錯誤。原因:我們在 Windows 上讓 AI 代理透過它的 Bash 工具下指令,實測指令裡成對的反斜線送到 Python 手上少了一層,\\b 變成 \b;而 Python 一般字串裡的 \b,官方字串跳脫說明定義是「ASCII Backspace (BS)」,也就是退格字元,不是詞界。正規式裡多了一個退格字元,當然永遠對不上。

怎麼修:含反斜線的程式一律寫成 .py 檔再執行,不要塞在一行指令裡;正規式用 raw 字串 r"\bcat\b"、單反斜線。我們重跑的結果:

p1 = "\bcat\b"    # 一般字串,\b 是退格字元,碼位 [8, 99]
p2 = r"\bcat\b"   # raw 字串,\b 是詞界,碼位 [92, 98]
re.search(p1, "a cat here")   # None,永遠不命中
re.search(p2, "a cat here")   # 命中

這個坑最麻煩的是「假修好」:如果把壞的寫法和修好的寫法都放在同一行指令裡做替換,兩邊會被吃掉同一層,替換前後一模一樣,程式卻印出「已修正」。所以改完一定要拿一個該中的字串跟一個不該中的字串實際跑一次。

坑二:open(path, "w") 先清空檔案,寫壞就歸零

現象:2026 年 9 月 21 日,一個重要的索引檔變成 0 bytes。程式有噴錯,但檔案已經回不來。原因:Python 官方文件寫 'w' 模式是「open for writing, truncating the file first」,打開的那一刻檔案就清空了;接著 write() 才因為字串裡有一個落單的代理字元編碼失敗。舊內容沒了,新內容也沒寫進去。

怎麼修:先寫到暫存檔,寫完再用 os.replace() 換掉原檔。os.replace 的說明寫成功時「the renaming will be an atomic operation」,寫到一半失敗的話,原檔不會被動到。我們用同一個會出錯的字串重跑:直接覆寫的檔案變成空的;改成暫存檔寫法,寫入一樣失敗,但原檔大小前後不變。

tmp = path + ".tmp"
with open(tmp, "w", encoding="utf-8", newline="\n") as f:
    f.write(new_text)       # 先完整寫進暫存檔
os.replace(tmp, path)       # 成功才取代原檔

同一行還藏了第二個坑:Windows 的文字模式會把每個 \n 寫成 \r\n,官方文件寫明 newline 沒指定時,換行會轉成系統預設的 os.linesep。我們有一次只加 11 行,diff 卻顯示 135 行全改,JSON 照樣讀得到,只有比對備份才看得出來。所以寫檔一律指定 newline="\n",寫完用 diff 看差異行數是否剛好等於你改的行數。

坑三:中文旁邊的英文詞,\b 卡不到邊界

現象:寫了 \bSEO\b 想抓文章裡的 SEO,結果「找SEO公司」這種寫法完全抓不到,加了空格的「找 SEO 公司」才抓得到。原因:Python 正規式文件寫 \b 是「字元」和「非字元」之間的邊界,而 Unicode 模式下的字元「includes all Unicode alphanumeric characters」,中文字也算。「找」和「S」都是字元,中間沒有邊界。

怎麼修:改成「前後不是英文字母」:(?<![A-Za-z])SEO(?![A-Za-z])。我們重跑的對照組:

測試字串 應該抓到嗎 \bSEO\b 前後不是英文字母
找SEO公司 要 沒抓到 抓到
找 SEO 公司 要 抓到 抓到
SEOUL 首爾 不要 沒抓到 沒抓到
GEOSEO 不要 沒抓到 沒抓到

同一類的坑還有兩個:比對 HTML 標籤要寫 <title[^>]*>,不要假設 title 後面緊接 >,因為標籤可能帶屬性;markdown 的 ** 夾在字中間時,「主關鍵字」在原始檔裡會變成 主**關鍵字**,直接比對會失敗,要先剝掉格式符號再比。

坑四:正規式字元類放多字元詞,每個字各自生效

現象:一個表單解析程式,名字裡有「定」「真」這類字的客人,資料被切斷或被判成「資料不全」。原因:程式想「抓到下一個欄位標籤為止」,就把欄位標籤詞全部放進 [^...] 字元類。字元類只認單一字元,等於把標籤詞拆成 15 個單字,名字裡出現任何一個都會被當成邊界。

怎麼修:邊界改用完整標籤詞的負向前瞻,例如「後面不是『電話:』這整串」,而不是「不是電、話、:這三個字」。寫完拿一個名字含標籤字的樣本測,確認能完整抓到。

坑五:白名單兩個條件永遠不可能同時成立

現象:後台上傳的圖片永遠進不了發佈,縮圖網址永遠 404,更糟的是編輯一次文章,舊圖就被靜悄悄剝光。API 層的 22 項測試全綠,沒有一項抓到。原因:檔名檢查寫成「每個字都在 0~9、a~f 和點號裡」而且「結尾是 .webp」。.webp 裡的 w、p 不是 16 進位字元,兩個條件永遠不可能同時成立,合法檔名全部被自己的白名單拒絕。

怎麼修:主體和副檔名拆開驗,副檔名對副檔名清單、主體對字元白名單,另外擋 /、\、..。白名單寫完立刻拿一個已知合法的檔名跑一次,白名單的負面測試是「合法的要過」。我們重跑:3fa9c0d1.webp 用舊寫法被拒、用拆開驗的寫法通過;3fa9c0d1.png 與 ../x.webp 兩種寫法都擋。

坑六:退出碼 0 不代表程式跑過

現象:一支要掃 137 頁的檢查程式,回傳 exit 0,報告卻只有 2 行,一頁都沒掃。原因:它本來就在背景執行,又被包了一層 nohup … &,外層提早結束,裡面的程式被收掉,回傳的 0 是外層的。另一次是 Windows 排程用 pythonw 跑,sys.stdout 是 None,程式一印東西就失敗,排程畫面卻顯示「上次執行結果 0」。

怎麼修:長任務的驗收看三件事:輸出裡有沒有「結束」那一行、產物的修改時間是不是今天、產物內容裡的時間戳是不是今天。三件都對才算跑過。排程類的任務也一樣,看產物有沒有長出新的一行,不看排程畫面的結果碼。

坑七:用管線把腳本送上主機,後半段被別的程式吃掉

現象:2026 年 10 月,代理用「把腳本轉成 base64、在主機上解碼後用管線直接交給 sudo bash」的一行寫法,把一段維運腳本送到雲端主機執行;腳本裡用到 ffmpeg 或 apt 的步驟之後,後面的指令沒有照預期執行。原因:這種寫法下,bash 是一邊從標準輸入讀腳本、一邊執行;ffmpeg、apt 這類程式也會讀標準輸入,把 bash 還沒讀到的腳本內容讀走了。同一批維運還有一個小坑:.env 設定檔最後一行沒有換行時,用 echo >> 追加的新設定會黏在上一行後面,兩個設定一起壞掉。

怎麼修:腳本先寫成主機上的檔案,再用 sudo bash 檔名 執行,標準輸入就不會跟腳本內容搶。改完設定檔之後,用程式實際把設定讀回來逐項核對,不要只看指令有沒有報錯。

坑八:代理看畫面下結論,資料其實在 API 裡

現象:2026 年 9 月 22 日,代理替我們整理某品牌官網的活動說明,看完渲染後的頁面就回報「官方沒有公開條款」,只照活動圖上印的 2~5 行字抄。實際上那個網站的 API 有一個欄位,存著 12 檔活動、合計 15,658 字的完整條款。原因:單頁式應用(SPA)的畫面是渲染出來的結果,不是資料本身;介面沒展開的欄位,不代表資料不存在。代理用「畫面上看得到什麼」去回答「官方有沒有公開」,答案就錯了。

怎麼修:面對單頁式網站,先看瀏覽器的網路請求裡有沒有 /api/ 開頭的呼叫,有的話直接讀那支 API,把回傳的所有欄位列出來再下結論;能用程式抓的就寫成腳本,不要手抄,手抄的內容下次網站改版就過期了。

坑九:Git Bash 偷改「/」開頭的參數,監控從建立那天就是壞的

現象:一台雲端主機的外部監控,叫過一次之後就一直停在「告警中」,後來主機再當機也不會再叫。原因:在 Windows 的 Git Bash 下用 gcloud 建健康檢查,參數裡的路徑 /health 被 Git Bash 當成檔案路徑,改寫成 /C:/Program Files/Git/health,監控從建立那天起打的就是一個不存在的網址,永遠 404。

怎麼修:在 Git Bash 下帶「/」開頭的參數時,前面加 MSYS_NO_PATHCONV=1 關掉路徑轉換,或改用 PowerShell 下指令。監控建好之後,回頭讀一次它實際設定的路徑,再自己打一次那個網址確認回 200。監控為什麼要放在服務外面、上線要配哪些基本設施,會員機器人那篇已經講過,這裡要補的是:監控本身也要驗。

坑十:錯誤被吞掉,空名單被當成真資料

現象:一個會員通知程式突然把所有人都判成「老會員」,幾天前的舊單被當成新事件重新發通知。另一次是後台被登出後,程式查會員全部回「找不到帳號」,一批人被誤寫成沒通過驗證,資料同步顯示「成功 0 筆」也沒有告警。原因:抓名單失敗的例外被 catch 吞掉,程式拿著空名單往下判斷;查後台頁面時,沒驗「該有的欄位在不在」,登出後的空白頁被當成「查無此人」。

怎麼修:名單抓不到或是空的,整輪直接跳過,不准往下判;抓後台頁面時,每種頁面都先檢查該有的欄位,欄位不在就報錯,不能當成 0 筆。再做一個可以手動開關的「故意失敗」設定,用它實際測一次失敗路徑。

第三種吞錯誤的方式更安靜:排程裡標成「軟失敗」的抓資料步驟,失敗時只寫一行 log、不中止流程,所以也不會告警,網頁就靜靜停在舊資料。修法是另加一道新鮮度守門,照資料本身的更新週期推算「現在至少該有到哪一天的資料」,落後 2 天以上就擋下建站並通知。

守門要用退出碼擋:Claude Code hooks 怎麼設才真的擋得住

我們在 2026 年 9 月學到的一句話是「文字不會擋人,退出碼會」:寫在規範裡的規則,代理可能照做、可能忘記;寫成程式、用退出碼擋下的規則,忘了也過不去。Claude Code 官方的記憶與 CLAUDE.md 說明跟這句一致,原文是「Claude treats them as context, not enforced configuration.」,同一段接著寫「To block an action regardless of what Claude decides, use a PreToolUse hook instead.」。

Claude Code hooks 是在代理執行工具前後自動跑的指令,官方 hooks 文件寫明它看的就是退出碼。這裡有一個很容易踩的坑:只有退出碼 2 會擋,其他非 0 的退出碼(包括 Python 程式出錯時預設的 1)都只算「非阻擋錯誤」,動作照樣執行。

退出碼 Claude Code hooks 的行為(官方文件) 一般部署腳本的慣例
0 成功,動作照常進行;可以印 JSON 做更細的決定 成功,進下一關
2 擋下動作,例如 PreToolUse 會擋下這次工具呼叫,stderr 的內容會給代理看 失敗,中止
其他(例如 1) 非阻擋錯誤,動作照樣執行,除非這個 hook 設成失敗也要擋 失敗,中止

官方原文是「Exit with code 2 to block the action.」,還特別提醒 1 雖然是 Unix 慣用的失敗碼,在這裡不會擋,「If your hook is meant to enforce a policy, use exit 2.」。所以拿部署守門改寫成 hook 時,不能直接沿用「失敗回 1」的習慣,擋下的分支要明確 sys.exit(2)。

另外兩件事也要想清楚。hook 程式自己當掉或根本沒啟動(例如設定檔裡的路徑打錯),預設同樣算非阻擋錯誤,動作照樣執行;官方文件提供 onFailure 設成 block 的選項,讓 hook 失敗時也擋下,文件標註需要 v2.1.295 以上的版本。寫好之後一樣要做負面測試:故意觸發一次該擋的情況,確認工具呼叫真的沒被執行。

規則放哪裡:CLAUDE.md、筆記檔、Skill、hook 的差別

規則放錯地方,代理就會「知道但沒做」。我們 2026 年 9 月 21 日的教訓:規則散在 20 個筆記檔裡,沒有自動觸發機制,要靠代理自己想起來去讀,結果同一天漏了 5 件事。後來把流程搬進 Skill,把一定不能錯的檢查做成會回傳退出碼的守門,守門上線當天就擋下我們自己的作品兩次。

放法 什麼時候被讀到 會不會擋下動作 適合放什麼
CLAUDE.md 每次對話開場都載入(官方:「at the start of every session」) 不會,官方說是 context 不是強制設定 每次都要知道的短規則
分散的筆記檔 沒有自動觸發,要代理自己想起來去讀 不會 案例、背景、為什麼這樣做
Skill 開場只載入名稱與描述,官方表格寫每個約 100 token;任務對上才載入全文 本身不會,裡面附的檢查程式可以 偶爾才用到的完整流程
hook 與部署守門 每次工具呼叫前後、每次部署前 會,看退出碼 絕對不能犯的錯

分層的原則是:越常用、越短的放越上層;越不能錯的,越要變成程式。Claude Code 官方也建議 CLAUDE.md 只放每次都要用的事實,多步驟流程或只跟某一塊有關的內容改放 Skill。

先驗尺再量:每把檢查都要有正反對照組

任何新寫的檢查程式,在拿它的輸出下結論之前,都要先跑兩組樣本:一組一定該中(沒中就是尺壞了),一組一定不該中(中了就是誤報),兩組都對才准用。只跑其中一組不算。我們 2026 年 9 月 20 日一天之內,三次把壞掉的尺量出來的結果當成結論:顯示卡記憶體取樣、簡體字掃描、關鍵字互搶判斷,其中一次還把錯的結論傳給另一個工作階段。關鍵字互搶那次,壞掉的尺把「標題都有同一個詞」當成互搶,正確做法是看完整查詢與頁面的交叉表,關鍵字自食那篇有完整步驟。

一把新檢查從寫好到可以拿來下結論

  1. 寫好檢查代理寫完程式,先不要拿它去量真正的東西
  2. 跑一定該中的拿已知有問題的樣本,檢查必須報錯
  3. 跑一定不該中的拿已知正確的樣本,檢查必須放行
  4. 故意改壞一次把守門接進流程後再塞壞樣本,確認部署真的停下
  5. 驗最終產物看線上頁面、檔案大小與筆數,不看有沒有報錯
示意圖:新寫的檢查程式要先通過正反兩組對照與一次故意改壞,才能拿來判斷真正的產物

量出來的東西跟觀察打架時,先懷疑尺,不要先解釋現象。這條也適用在代理身上:代理回報的結論是另一把尺,轉述給別人之前要自己驗過。網站的日期守門也是同一套邏輯,我們在 sitemap 日期那篇寫過,建站連跑兩次、日期變動必須是 0,就是一組「一定不該中」的對照。

代理不是開越多越好:token 與連線的上限

用 AI 寫程式時開多個代理平行做事很快,但兩種資源會先撞牆。2026 年 9 月我們一次派 5 個大模型代理做稽核,每個約吃 20~30 萬 token,直接撞到每週用量上限;後來把機械性的檢查(數字對不對、連結在不在、字數夠不夠)改寫成程式跑,代理只做需要判斷的部分。

另一個是本機連線數。2026 年 10 月讓代理寫壓力測試在 Windows 本機跑,一次開約 240 條新連線就被系統拒絕,測出來的「失敗」其實是本機的限制,不是服務的問題;改成同時 150 條才量得到真正的結果。兩件事的共同點是:數字不對勁時,先確認是不是自己的環境到頂了。

自己用AI寫程式之前,先想清楚的 5 件事

不管你是工程師還是行銷人,用 AI 寫程式之前先確認這五件事,能少掉大部分的坑:

  1. 驗收標準是什麼:寫下「什麼產物長什麼樣才算完成」,例如「這 137 頁每頁都有報告」,而不是「程式跑完沒報錯」。
  2. 有沒有正反對照組:每個檢查準備一個一定該中、一個一定不該中的樣本,交給代理時一起給它。
  3. 哪些規則要變成程式:一定不能錯的事(上線前的檢查、不准動的檔案)寫成會回傳退出碼的守門或 hook,不要只寫在說明文件裡。
  4. 寫檔怎麼保護原檔:要覆寫重要檔案前先備份,程式一律先寫暫存檔再取代。
  5. 誰來看最終結果:線上頁面、資料筆數、通知有沒有發出去,至少要有一個人或一支程式看過真正的產物。

用 Claude 寫程式能省下大量打字的時間,但「驗收」這件事沒辦法省。代理可以替你跑檢查,前提是那些檢查本身被驗過。更多系統面的實作紀錄,在我們的系統與自動化主題頁。

我們的方案:自動化程式與網站維運

這篇裡的每一道防呆,都是我們在 AI寫程式的日常裡,替自己和客戶寫自動化程式、建網站時實際在用的:正反對照組、單一腳本的部署守門、監控本身的驗收、寫檔前備份。如果你需要寫一套自動化程式、讓排程或後台串接穩定跑下去,可以看自動化程式服務,依功能報價,評估不收費。

要建一個一開始就裝好部署守門的網站,可以看 SEO 建站方案:

方案 費用 內容
建置 $900 USDT 站台架構、技術 SEO、初始內容
月維護 $400 USDT/月 內容產出、內鏈維護、索引監控

完整方案在價格頁。

常見問題

AI 寫的程式可以直接上線嗎? 不建議直接上線。AI 寫程式的速度很快,但它回報的「成功」來自過程而不是結果;上線前至少要跑過正反對照組、讓部署守門用退出碼把關,並由人或程式看過最終產物。

Claude Code hooks 回傳退出碼 1 會擋下工具呼叫嗎? 不會。官方文件寫明只有退出碼 2 會擋下動作,其他非 0 的退出碼都算非阻擋錯誤,動作照樣執行;要擋就明確回傳 2,並考慮把 hook 設成自己失敗時也擋下。

CLAUDE.md 寫了規則,代理為什麼還是會犯? 因為 CLAUDE.md 只是給代理參考的內容,不是強制設定。官方原文說 Claude 把它當成 context,要不管代理怎麼判斷都擋下某個動作,就改用 PreToolUse hook。

為什麼含反斜線的程式要寫成檔案再執行? 因為指令傳遞過程中反斜線可能少一層,而且失敗時不會報錯。我們實測過 \\b 到 Python 手上變成退格字元,正規式永遠不命中;寫成 .py 檔再執行就沒有這個轉換。

不會寫程式的人,能用 Claude 寫程式嗎? 可以寫出能動的程式,但驗收需要有人看得懂產物。最少要做到兩件事:說清楚「完成」長什麼樣子,並且親自看過一次真正的結果,例如打開線上頁面、數一次資料筆數。

這類問題,我們天天在解

把你的情境描述給我們,直接告訴你做不做得到、大概多少錢。

用 Telegram 聊需求
評估與報價不收費 · 回覆你的是工程師本人
TG 聊需求