Category: Building in public

Notes from building this practice in the open, including the things that broke.

  • The form saved every lead and showed visitors a 404

    A form on my site had a field called name. Reasonable field name. It broke the page in a way that took me a while to understand, because it broke it in both directions at once.

    What the visitor saw

    They filled in the form, pressed submit, and got “Page not found.”

    What actually happened

    The submission was received. It was validated. It was stored. Everything worked.

    WordPress reserves a set of public query variables — name, author, cat, paged, order and a couple of dozen others. When a request arrives carrying one of them, WordPress tries to resolve a post with that slug. There was no post called “Brij Raj Singh”, so it decided the request was a 404 and picked the 404 template.

    But the hook my handler runs on fires after that decision and before the template renders. So the lead was saved perfectly, and then the visitor was shown a page telling them nothing existed.

    Why this one is nastier than a normal bug

    If the form had simply failed, I would have found it in a day. Someone would have said “your form is broken” and the fix would have been obvious.

    Instead the two halves disagreed. My database said the form worked — leads were arriving, so from the inside there was no problem to investigate. The visitor’s screen said it did not. And the people best placed to report it were the ones who had just been told the page did not exist, which is not a state that inspires anyone to write in and mention it.

    Any lead that came from someone who did not already know me would have been lost at exactly the moment they were most willing to talk.

    The fix, and the wider point

    Every field on the site now carries a prefix, generated through one helper so nobody can add a field that skips it. It sidesteps the entire class of collision rather than fixing the one field that happened to hit it.

    The wider point is about how I now test things. It is not enough to confirm the record arrived. You have to check what the person on the other side actually saw, in a browser, as a stranger — not logged in, not with your own cookies, not by reading the database and concluding it must have worked.

    Same principle as any delivery process. “The report was sent” and “the client understood where the project is” are different claims, and only one of them is usually measured.

  • My buy button 404d for a week and nothing told me

    I renamed my Gumroad account to tidy up the URL. The old one had a number in it that looked like a placeholder, and the new one matched the brand. It took about ten seconds.

    Every buy button on my site pointed at the old address. Gumroad does not redirect a renamed vanity URL. So every one of them started returning a 404.

    Nothing told me

    This is the part worth dwelling on. The site did not error. Analytics showed clicks on the buy button, exactly as before. Uptime monitoring was green, because my site was fine — it was the destination that had gone.

    From every angle I was set up to look at, things were working. The only signal available was an absence: no sales. And no sales is indistinguishable from a slow week when you are starting out.

    The class of failure this belongs to

    Loud failures are cheap. A 500 page gets noticed in an hour, because it is obvious and someone complains.

    Expensive failures are the ones where the system reports success. The click fires. The form submits. The page loads. Something further down the chain quietly does not happen, and every dashboard you own is looking at the wrong end of it.

    Delivery work has exactly the same shape. A status report that goes out on time but to a stale distribution list. An escalation raised in a channel nobody watches. A handover document written and never opened. The process ran. The outcome did not happen. And because the process ran, nothing flags.

    What I changed

    Two things, both small.

    Commerce destinations are no longer written into pages. They live in one setting, referenced by name, so changing where a button points is a single edit rather than a hunt through content. That is a fix for the specific bug.

    The more useful change was the habit: when I change an address, I now check the thing at the other end of it. Not the click. The arrival.

    It is a short list of places where that applies — payment links, form actions, webhook endpoints, redirect targets, notification addresses. Worth writing down once for whatever you run, because in every one of those cases the failure is silent and the metric you would normally trust keeps reporting green.