1. youtubeSignupRequired ≠ no channel
With youtube.upload as the only scope, the API can't identify the owned channel and throws an error that reads as "no channel." The channel existed.
→ Request youtube.readonly alongside.
2. 403 access_denied: a different account registered as test user
While the publishing status is "Testing," only registered test users can authenticate. The registered address and the one used to authenticate differed by one character, and finding that took hours.
★ It wasn't a typo. Both accounts were real. Treating one as a "typo" and cleaning it up would have broken a different feature.
→ Don't trust email addresses by eye; copy-paste them, and confirm which account every time.
3. A refresh_token in Testing status expires in 7 days
Fatal for automation. Publishing to production is mandatory.
If the publish button is greyed out, it's because the privacy policy and terms-of-service links on the branding page are empty. → Added /privacy and /terms routes directly to the app. Publishing works without verification; you just click through the "unverified app" warning once during auth.
Build the diagnostic tool first
One endpoint that shows the token's account, scopes, and channel at once. Don't guess; hit this first.