Fixing AI Problems? The 403 That Wasn't a Bug
I built an agent. I gave it a job: post to this blog on its own. I ran the OAuth flow, wired up the Blogger API, and hit run.
403 — caller does not have permission.
Fine. Auth bugs happen. I checked the scopes. Correct. I checked the token. Fresh. I regenerated it anyway, because that's what you do at 11pm when you're sure it's a token problem. Same 403. I started reading Stack Overflow threads about Blogger API quirks, half-convinced I'd found some undocumented rate limit or a formatting issue in the request body.
None of that was it.
Here's the thing thirty-plus years in this industry teaches you that no bootcamp does: when a failure looks exactly like the bug you've seen a hundred times before, that's precisely when you should stop trusting the pattern-match and go check the boring stuff first. I didn't, not for two hours. I went down the AI-flavored explanation — token scope, agent misconfiguration, API quirk — because that's the story that fits the "I'm building an AI agent" narrative I was living in that night.
The actual problem had nothing to do with AI at all. It was an identity mismatch, plain old IAM, the same category of problem I've been untangling for enterprise clients since before "cloud" was a word anyone used. The Google account that owned the blog wasn't the same Google account that had run the OAuth flow. One was my personal Google identity. The other was a Workspace account. The Workspace account could read the blog's public content fine — it had zero standing to write to it. No amount of correct code fixes a permission the account never had.
The fix, in the order it has to happen
If you're wiring an agent to post to Blogger for yourself, save two hours and do this in order:
- Confirm who owns the blog before you touch any code. Blogger → Settings → Permissions tells you. Don't assume it's the account you're about to authenticate as — that assumption is exactly what cost me the time.
- Set up your Google Cloud project and enable the Blogger API v3 specifically. Creating the project isn't enough; enabling the API is its own step, and it's the kind of thing that's easy to skip and hard to notice you skipped.
- Choose your OAuth consent screen type deliberately. If the account making the API calls is a Google Workspace account, go Internal — no verification review, no 7-day refresh token expiry to fight with later. If you're running this as a personal Gmail account with no Workspace behind it, you're on External, and you should know going in that it comes with a review process and a token that expires weekly until you're verified. That's not a footnote — it's the difference between "set it and forget it" and "why did this stop working a week later."
- Run OAuth as the account that will make the calls, and get your refresh token.
- Before you write a single line of posting code, check that account's actual role on the blog. If it's not there: send the invite from the owning account. Then confirm it was accepted — sent isn't accepted. "Invited" reads like "should work now." It isn't the same thing, and that gap is where I lost the most time. Then open the role dialog and click Save. There's a version of this screen where the role change looks selected but hasn't committed until you hit that button.
- Test with a disposable draft post first. This isolates a permission problem from a Pages-vs-Posts API quirk, which is a separate rabbit hole you don't want to fall into at the same time as the one you're already in.
- Never trust a 200 alone. For anything real, diff what you sent against what's live after the write. A successful response code tells you the request didn't error — it doesn't tell you the content landed the way you intended.
Why I'm telling you the wrong turn, not only the fix
Most write-ups of a bug skip straight to the answer. That's efficient, and it also quietly robs you of the one thing that helps next time: recognizing the shape of the problem before you're two hours deep in it. If I'd told you up front to check blog ownership vs. OAuth account, you'd nod and forget it by Thursday. Now you've got the memory of chasing the wrong thing first — and that's what you'll recall the next time a 403 shows up somewhere else in an agent build.
That's also the bigger pattern I keep running into as I build these agents: the AI part is rarely where things break. It's the boring infrastructure underneath it — identity, permissions, scopes, ownership — that trips people up, dressed up in a shiny new "agent" costume. Thirty-plus years of enterprise IT teaches you to suspect the plumbing before you suspect the magic. That instinct doesn't go away because the tool got smarter.
More of this as I build it — what worked, what broke, and what I'd do differently. Follow along.
Get the next one before it's public
I write these up as I hit them, not on a schedule. If you want the next fix before it's indexed anywhere, subscribe:
The list of 5,000+ things worth automating — the backlog I'm pulling these posts from — is heading to GitHub, public, soon. [🔒 Waitlist — coming soon]
Vote on what I build the next AI User Guide about
Every Vibe Coder hits the same handful of walls on the way to launching, monetizing, and scaling. I'm building a short, practical guide for whichever one you're stuck on right now. Cast a vote:
- 🔲 Getting from local build to a live domain (Vercel/Digital Ocean/AWS — which and why)
- 🔲 Stripe billing without getting your account flagged or frozen
- 🔲 Supabase auth + database setup that won't need a rebuild at 1,000 users
- 🔲 MCP servers and agents — what's actually production-ready vs. still a demo
- 🔲 Something else — tell me in the comments
(Poll mechanism TBD — see TODO list. For now this ships as a comment prompt; a real vote widget comes once traffic justifies it.)
Comments
Post a Comment