A YouTube video would not play in my community feed. The card sat there saying the content was blocked. I decided YouTube was being difficult, wrote code to detect it, shipped a warning for it, and went to bed feeling productive. Yesterday I found out the block was mine.
Here is the order things happened in, because the order is the whole story.
First I switched the embed iframe from youtube-nocookie.com to the standard www.youtube.com/embed. Small change, felt harmless. Videos stopped rendering. Instead of asking why, I reached for the explanation that let me off the hook: the video owner must have disabled embedding. Some creators do that. It is a real thing.
So I built a guard. At compose time, before a note went live, the server would hit YouTube's oEmbed endpoint and ask whether the video was embeddable. If the answer looked bad, the composer refused the post and told you the owner had disabled embedding. Neat little check. Had a test file and everything.
The check was wrong twice over
It started rejecting links that were completely fine. Paste a normal video, get told the owner disabled embedding, when the owner had done nothing of the sort. Turns out YouTube's oEmbed endpoint returns a 401 for plenty of videos that embed perfectly well. I had built a gate on top of an endpoint that lies, and the gate said no to real people trying to post real things.
That was the moment I actually went and looked at the browser instead of my own code's opinion of the browser. The iframe was being blocked by my Content Security Policy. My frame-src list still only allowed youtube-nocookie.com. I had changed the embed domain days earlier and never changed the policy that permits it. One domain in one header. That was the entire bug.
So yesterday I deleted the check, deleted its helper, deleted its tests, and added www.youtube.com to frame-src. Net effect: minus 82 lines, plus one word in a config file. Videos play.
What I actually learned
I diagnosed a symptom I had personally caused, invented an external villain for it, and then wrote defensive code to protect users from that villain. The code worked exactly as designed. It was just guarding the wrong door, and it locked out the people I built it for.
When something breaks right after you changed something, it is not a coincidence. It is a confession.
— Note to self
The honest ending is less tidy. Later in the day I removed the video post format from the composer entirely -- split Quiz into its own tab, killed post scheduling nobody used, made hashtags inline and clickable. So the feature I spent two rounds debugging is now gone. That is fine. I would rather cut a format than keep a half-trusted one.
Next time the browser says blocked, I read my own headers before I read anyone else's API.

