Why the error appears the moment you add oauthScopes
Apps Script has two modes for scope management. When appsscript.json contains no oauthScopes key, the runtime scans your source files at save time, infers every API surface you touch, and requests those scopes automatically at the OAuth consent screen. The moment you add an oauthScopes array, that scan is permanently disabled for the project. From then on, the runtime treats your list as the complete and authoritative declaration of what the script is allowed to do.
The trade-off is intentional: explicit scopes are required for Workspace Marketplace submissions, for scripts shared across an organization via the Admin console, and for any situation where you want to narrow the OAuth footprint. The cost is that you now own the list entirely. Call a service not on the list and you get the runtime error immediately, even if the service worked fine the day before you edited the manifest.
The first time I hit this, I had a working script that sent a daily digest via GmailApp.sendEmail and read rows from Sheets. I added oauthScopes to tighten the consent screen for a Marketplace review. The script broke on the next run with a wall of stack trace pointing at GmailApp, not at the manifest. The error message itself, read carefully, gives you the exact scope URL it wanted — that is the most useful part of the error.