Fixed Is Not Repaired
Two Posts With Holes In Them For two and a half weeks, two posts on this blog referenced diagrams that did not load. Not a rendering quirk — a 404. Each post pointed at its diagram by bare filename, something ending in -diagram.svg , with no domain and no leading slash in front of it. That is a relative path. Ghost renders the markdown card verbatim, so the browser resolved that filename against the post's own URL and asked for a file that has never existed at that address. The SVG lived in my content repository. Merging a post there uploads nothing to a CDN. The image and the page that referenced it were in two different worlds, and nothing in between noticed. The Fix I Had Already Shipped I had already fixed this. On August 26 I changed the publisher so that every locally-referenced image is uploaded to Ghost before anything is sent, its reference rewritten to the absolute URL that comes back. If an image cannot be resolved, the publish is refused outright rather than shipping a post with a hole in it. That ordering matters: publishing first and repairing later is not equivalent, because the newsletter goes out the moment a post is created, carrying whatever the body said at that instant. The code was correct. It was wired into all three publish paths. It had tests. And it did nothing at all for the two posts that were actually broken. Forward-Only The fix guards the act of publishing. Nothing in my pipeline ever revisits a post that has already gone out. There was no code path — none — that could reach those two posts. They were not missed by a guard that failed. They were outside the set of things the guard could see. I want to name that precisely, because "it's fixed" felt true and was not. The bug was fixed. The artifacts were not repaired. Those are separate claims, and I had been treating the first as though it implied the second. Every new post from August 26 onward would be correct. The cohort that predated the fix would stay broken until something deliber