YouTube Node: Créer une playlist génère une erreur 400 INVALID_ARGUMENT en production, mais fonctionne parfaitement dans les tests manuels de l'UI

Décrivez le problème/l’erreur/la question

Salut à tous, j’ai un problème vraiment étrange avec le nœud YouTube en essayant de créer dynamiquement une playlist. Ça fonctionne parfaitement quand je clique manuellement sur « Execute Step » dans l’interface n8n, mais dès que le workflow s’exécute en production (déclenchement automatisé/en direct), il échoue complètement avec une erreur 400 Bad Request.

Configuration et configuration du nœud

  • Ressource : Playlist

  • Opération : Créer

  • Expression de titre : {{ $json.artist_name }} - {{ $json.album_name }} (Full Release)

  • Paramètres : Execute Once est activé (pour éviter de boucler sur plusieurs éléments entrants).

Le comportement

  1. Dans le test manuel de l’interface : L’expression se résout parfaitement en une chaîne propre : « Zedd, Bright Lights - Follow You Down - Keys N Krates Remix » (environ 77 caractères, bien en dessous de la limite de 150 caractères de YouTube). Le nœud d’entrée (Match) transmet les deux champs JSON ainsi que les données d’informations binaires.

  2. Lors de l’exécution en production : La même structure de données arrive, la chaîne de titre devrait être identique, mais le nœud lève l’erreur API suivante.

Ce que j’ai déjà vérifié/essayé :

  • Google Cloud Console App : Défini en mode Production (pas en mode Testing/Sandbox).

  • Statut de confidentialité : Essayé à la fois Public et Private/Unlisted. Même erreur en production sur les deux.

  • Limites de caractères : Le titre ne fait que ~77 caractères.

  • Caractères spéciaux : Essayé d’utiliser une regex stricte pour supprimer tout sauf les caractères alphanumériques de base, mais l’erreur 400 persiste.

  • Présence du canal : Le compte Google dispose d’un canal YouTube actif et complètement créé, et d’autres nœuds (comme le téléchargement vidéo) fonctionnent correctement.

Pourquoi n8n se comporte différemment entre l’exécution manuelle et une exécution en production automatisée lors de l’analyse ou de l’envoi de cette charge utile à YouTube ? Avez-vous des idées sur comment déboguer ou contourner ce problème ?

Veuillez partager votre workflow

Partagez la sortie renvoyée par le dernier nœud

Informations sur votre configuration n8n

  • Version n8n : v2.23.2
  • Base de données (par défaut : SQLite) : par défaut
  • Paramètre EXECUTIONS_PROCESS de n8n (par défaut : own, main) : main
  • Exécution de n8n via (Docker, npm, cloud n8n, application de bureau) : Docker
  • Système d’exploitation : Raspberry Pi OS 64-bit Debian 13 trixie (aarch64)

Les tests d’interface utilisateur manuels peuvent masquer l’incompatibilité car ils s’exécutent sur l’élément actuellement sélectionné dans l’éditeur. Dans l’exécution de production défaillante, la seule entrée qui compte est le panneau d’entrée directement sur le nœud YouTube, et non le nœud Match en amont.

Vérifiez ce panneau pour l’élément que le nœud YouTube a réellement reçu. Si artist_name / album_name sont manquants là ou proviennent d’un élément appairé, figez le titre dans un nœud Set/Edit Fields juste avant YouTube et mappez le titre de la playlist à partir de ce nouveau champ. Si le champ est déjà une chaîne de caractères simple là, publiez cet élément d’entrée du nœud YouTube masqué plus le corps de réponse 400 complet.

Hey, merci pour ta réponse. J’ai restructuré le workflow pour utiliser le nœud Merge en mode combine (comme on peut le voir en pièce jointe) pour assurer que les données binaires et les métadonnées JSON restent parfaitement synchronisées tout au long du pipeline.

Alors, tout semblait parfait jusqu’à l’exécution ici. Concernant ta réponse, j’ai pensé que je pouvais appliquer la même situation pour télécharger des vidéos. Cependant, ça n’a pas fonctionné. J’ai aussi changé le mode de mon nœud merge en combine. Malheureusement, ça n’a pas marché. Tu peux trouver le statut le plus récent de mon workflow ci-dessous.

Merci. Les captures d’écran ne montrent toujours pas l’entrée du nœud YouTube échouée, donc le mode Fusion se trouve une étape en amont de ce qui décide cela.

Ouvrez l’exécution de production échouée, cliquez sur le nœud YouTube lui-même, et copiez un élément JSON d’entrée floutée de ce nœud ainsi que le corps de réponse 400 complet. Si ce nœud reçoit déjà une chaîne de titre de playlist simple, la vérification suivante est la charge utile exacte que YouTube rejette ; s’il ne la reçoit pas, la correction se trouve immédiatement avant YouTube.

Vous avez tout à fait raison. Le correctif du nœud Merge a résolu le problème de téléchargement vidéo, mais l’erreur 400 initiale de Playlist se produisait effectivement en amont avant même que le nœud Merge ne s’exécute.

Comme le workflow fonctionne maintenant sans problème en production après avoir reconstruit cette section, je suis retourné aux anciens journaux d’exécution échoués pour récupérer exactement ce que le nœud YouTube Playlist a reçu dans son panneau d’entrée lors du crash, juste pour satisfaire l’analyse des causes profondes.

Voici le JSON masqué du panneau INPUT du nœud YouTube Playlist défaillant :

{
"json": {
"album_name": "Follow You Down - Keys N Krates Remix",
"artist_name": "Zedd, Bright Lights"
}
}

Et l’expression sur le champ Title était :
{{ $json.artist_name }} - {{ $json.album_name }} (Full Release)

Bien qu’elle se soit résolue visuellement correctement dans l’aperçu de l’interface utilisateur, lors de cette exécution spécifique en production, n8n perdait le contexte d’élément appairé car le flux d’entrée provenait directement d’un nœud binaire multi-éléments sans ancrage d’index d’élément explicite (comme l’utilisation de .item.json). YouTube recevait donc probablement une chaîne de charge utile vide ou mal formée en arrière-plan.

Maintenant, j’ai quelques questions :

1- Vous avez dit que :

« Le test manuel de l’interface utilisateur peut cacher l’inadéquation car il s’exécute par rapport à l’élément actuellement sélectionné dans l’éditeur. »

Alors, comment puis-je le tester ? Est-ce toujours en production ou existe-t-il un environnement spécial ?

2- Quand j’ai commencé à exécuter le workflow (publié), il démarre parfaitement, mais des erreurs commencent à se produire sans raison apparente. Par exemple, des erreurs liées aux expressions, etc. Pourquoi cela se produit-il alors qu’il n’y a aucun problème ?

Merci.

Excellente investigation en fouillant dans les anciens journaux d’exécution.

Sur la question 1 — tester le comportement de production sans déclencheur actif :
La façon la plus propre est d’utiliser le bouton « Test workflow » (l’icône de lecture en haut de la toile quand le workflow est actif/publié). Cela exécute le workflow exactement comme en production, en utilisant le déclencheur réel — pour les workflows basés sur webhook, cela met n8n en état d’écoute pour un appel entrant réel. Vous pouvez aussi envoyer manuellement une charge test à votre URL webhook depuis un outil comme Postman ou curl en mode test. Cela vous donne une vraie exécution en production que vous pouvez inspecter, pas une exécution simulée.

Sur la question 2 — erreurs d’expressions aléatoires après la publication :
C’est presque toujours le contexte des items qui se casse quelque part en amont. Quand un workflow s’exécute en direct, chaque nœud ne voit que les items qui lui sont transmis du parent direct — si vous avez une branche ou un nœud qui retourne une forme différente de ce que vous avez testé, les expressions qui fonctionnaient en mode manuel commencent à générer des erreurs. La solution est d’ajouter un nœud « Set » (Edit Fields) juste avant n’importe quel nœud qui utilise des expressions de plus tôt dans la chaîne, en remappant explicitement les champs dont vous avez besoin. De cette façon, la forme des données est toujours explicite et ne dépend pas de ce qui a été sélectionné dans l’éditeur lors de votre test.

Salut, juste une mise à jour avant de passer ça en production, le problème persiste toujours. Le nœud Merge n’a pas fonctionné, et j’ai essayé plusieurs façons différentes de transmettre des données binaires via le nœud Code mais je n’ai toujours pas pu le faire fonctionner correctement. Merci de l’aide quand même !

Code de correspondance :

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;