描述問題/錯誤/問題
大家好,我在使用 YouTube Node 動態建立播放清單時遇到一個非常奇怪的問題。當我在 n8n UI 中手動點擊「Execute Step」時,它完美無缺,但一旦工作流程在生產環境中運行(自動化/實時觸發),它就會完全失敗,出現 400 Bad Request 錯誤。
Node 配置與設定
行為
-
手動 UI 測試中: 運算式完美解析為乾淨字串:"Zedd, Bright Lights - Follow You Down - Keys N Krates Remix"(約 77 個字元,遠在 YouTube 150 字元限制以內)。輸入 node(Match)會傳遞 JSON 欄位和二進制資訊資料。
-
生產環境運行中: 傳入相同的資料結構,標題字串應該相同,但 node 拋出以下 API 錯誤。
我已檢查/嘗試過的內容:
-
Google Cloud Console App: 設定為 Production 模式(不在 Testing/Sandbox 中)。
-
隱私狀態: 同時嘗試了 Public 和 Private/Unlisted。在生產環境中兩者都出現相同錯誤。
-
字元限制: 標題只有 ~77 個字元。
-
特殊字元: 嘗試使用嚴格的正規表達式來移除除了基本英數字元外的所有內容,但 400 錯誤仍然持續。
-
頻道存在: Google 帳戶有一個活躍且完全建立的 YouTube 頻道,其他 node(如影片上傳)運作正常。
當解析或將此酬載傳送到 YouTube 時,為什麼 n8n 在手動執行和自動化生產環境運行之間的行為不同?有任何想法可以幫助除錯或繞過這個問題嗎?
請分享您的工作流程
分享最後一個 node 傳回的輸出
關於您的 n8n 設定的資訊
- n8n 版本: v2.23.2
- 資料庫(預設: SQLite): 預設
- n8n EXECUTIONS_PROCESS 設定(預設: own, main): main
- 執行 n8n 的方式(Docker、npm、n8n cloud、desktop app): Docker
- **作業系統: Raspberry Pi OS 64-bit Debian 13 trixie (aarch64)
手動 UI 測試可能會隱藏不匹配問題,因為它會針對編輯器中目前選取的項目執行。在失敗的生產執行中,唯一重要的輸入是 YouTube 節點上的直接輸入面板,而不是上游的 Match 節點。
檢查該面板中 YouTube 節點實際接收到的項目。如果 artist_name / album_name 遺失在該處或來自配對項目,請在 YouTube 之前的 Set/Edit Fields 節點中凍結標題,並從該新欄位對應播放清單標題。如果該欄位已經是純字串,請貼上經過編輯的 YouTube 節點輸入項目加上完整的 400 回應本文。
嘿,感謝你的回答。我重新組織了工作流程,使用combine模式下的Merge節點(如附件所示),以確保二進位資料和JSON中繼資料在整個管道中保持完美同步。
一切看起來都很完美,直到執行到這裡。根據你的回答,我認為我可以將相同的情況應用到影片上傳。但是,這行不通。我也將我的merge節點模式更改為combine。不幸的是,它還是沒有起作用。你可以在下面找到我工作流程的最新狀態。
感謝。螢幕截圖仍未顯示失敗的 YouTube 節點輸入,所以 Merge 模式位於決定此問題的上游一步。
開啟失敗的生產執行,點擊 YouTube 節點本身,並從該節點複製一個已編輯的輸入 JSON 項目加上完整的 400 回應內文。如果該節點已接收純文字播放清單標題字串,下一個檢查是 YouTube 拒絕的確切負載;如果沒有,修復位於 YouTube 的前一步。
你說得完全對。Merge 節點的修復解決了影片上傳問題,但最初的 Playlist 400 錯誤確實是在 Merge 節點執行之前就在上游發生的。
由於工作流程在我重建該部分後現在在生產環境中運行順暢,我回過頭查看舊的失敗執行日誌,以獲取 YouTube Playlist 節點在崩潰期間在其輸入面板上收到的確切內容,只是為了滿足根本原因分析的需要。
以下是來自失敗的 YouTube Playlist 節點的 INPUT 面板的編輯後 JSON:
{
"json": {
"album_name": "Follow You Down - Keys N Krates Remix",
"artist_name": "Zedd, Bright Lights"
}
}
而 Title 欄位上的表達式是:
{{ $json.artist_name }} - {{ $json.album_name }} (Full Release)
儘管它在 UI 預覽中視覺上解析得很好,但在那次特定的生產運行中,n8n 丟失了配對的項目上下文,因為輸入串流直接來自多項目二進制節點,沒有明確的項目索引錨定(例如使用 .item.json)。所以 YouTube 可能在幕後收到了空的或格式不正確的有效負載字符串。
現在,我有一些問題:
1- 你說過:
「手動 UI 測試可以隱藏不匹配的情況,因為它針對編輯器中目前選定的項目運行。」
那麼,我怎樣才能測試呢?它總是在生產環境中,還是有什麼特殊環境?
2- 當我開始運行工作流程(已發佈)時,它開始得很完美,但之後開始出現一些錯誤,沒有任何原因。例如,表達式相關的等等。為什麼即使沒有問題也會發生這種情況?
謝謝。
做得很好,挖掘了舊的執行日誌。
關於問題 1 — 在沒有即時觸發的情況下測試生產行為:
最乾淨的方式是使用「Test workflow」按鈕(工作流程為活躍/已發佈狀態時,畫布頂部的播放圖示)。這會完全按照生產方式執行工作流程,使用實際的觸發器 — 對於以 webhook 為基礎的工作流程,它會讓 n8n 進入監聽狀態以接收一個真實的傳入呼叫。你也可以在此模式下使用 Postman 或 curl 等工具手動 POST 測試負載到你的 webhook URL。這樣你就能獲得一個真實的生產執行,可以檢查,而不是模擬的。
關於問題 2 — 發佈後出現隨機表達式錯誤:
這幾乎總是由於項目內容在上游某處破裂。當工作流程即時運行時,每個節點只能看到從直接父節點傳遞給它的項目 — 如果你有一個分支或節點返回的形狀與你測試時不同,在手動模式中有效的表達式就會開始拋出錯誤。修復方法是在任何使用來自鏈前面表達式的節點前面添加一個「Set」(Edit Fields)節點,明確重新映射你需要的欄位。這樣資料形狀總是明確的,不依賴於你測試時在編輯器中選擇的內容。
嘿,在將此移至生產環境之前先更新一下,問題仍然存在。Merge 節點沒有起作用,我試過了幾種不同的方式透過 Code 節點傳遞二進制數據,但仍然無法正常運行。不過還是感謝你的幫助!
Match code:
const jsonData = $("Multi-track splitter").all();
const videoFiles = $input.all();
let matchedItems = [];
const normalize = (str) => str ? str.toLowerCase().replace(/[^a-z0-9]/g, '') : '';
for (const item of jsonData) {
const song = item.json;
const safeSongName = normalize(song.song_name);
const match = videoFiles.find(v => {
const fileName = v.json.fileName || '';
const cleanFileName = fileName.replace('.mp4', '').replace(/_\d+$/, '');
const safeFileName = normalize(cleanFileName);
return safeFileName.includes(safeSongName) || safeSongName.includes(safeFileName);
});
if (match) {
matchedItems.push({
json: {
...song,
yt_description: `Artist: ${song.artist_name}\n\nAlbum: ${song.album_name}\n\nRelease Date: ${song.release_date}\n\n${song.company_name}\n${song.publisher_name}\n\nNOT auto-generated by YouTube.`,
yt_title: `${song.artist_name} - ${song.song_name}`
},
binary: match.binary
});
}
}
return matchedItems;