In this, the second entry of our bug tales series, a single letter will be causing a lot of trouble.

It was a sunny and warm spring morning in Madrid. I was sipping my freshly brewed coffee when a disturbing ticket arrived to our support queue. John, one of our long time customers, was contacting us because we had charged his credit card but he was missing the invoice for his last subscription fee.

- Rats and horses! - I thought, like I always do when we get a bug report from a customer.

Promptly I started getting all the facts straight. I checked John's account on DNSimple and verified when he had last been invoiced. Immediately something caught my eye: the invoice was there, but it was marked as dunned. Could it be possible that John was wrong?

- It has happened before - I mumbled…

I had to verify whether we had charged the customer, so I did the only thing I could do: open our payment processor's website. I went to the customer's subscription profile and, there it was… The successful renewal of his subscription.

- So the customer is right and we have a bug… Nothing new under the sun. - I said to myself.

Immediately I created an issue on our tracker and assigned it to myself. I was really eager to get to the bottom of this matter. I opened my editor and browsed the code that was dealing with creating invoices for subscription renewals. We were generating the invoices based on webhooks sent by our payment provider. Depending on the webhook type we would generate the invoice in a different state: either dunned or collected.

- That's my first clue, Haskell.- I told my cat as he kept licking his paws.


The next thing I needed to know was whether the subscription renewal had been successfully paid on the first attempt. I knew where to look as I still had a browser tab open with our payment provider's website.

Scrolled down and there it was: the subscription had been dunning for several days and automatically canceled. Then it was paid for and reactivated.

- So the invoice was correctly generated the first time but wasn't marked as collected once the renewal was paid for. - I thought.

Time to keep pulling the thread: how was a dunned invoice marked as collected?

I switched back to my editor and started reading code again. It turned out that we were using a third type of webhook to do this. Could we have missed this particular event? According to our monitoring we had successfully processed all incoming webhooks, but that wasn't good enough…

I jumped to the console and looked for all the events that we had received for that subscription. It didn't take long for me to find it.

- It's not that, then.

Back on my editor I started looking at the webhook handler. Could there be something wrong in it? It was fairly simple, we only checked a one thing from the payload: The state transition of the subscription. We verified both state and previous_state.

- Wait. No. It cannot be that.

Something had caught my eye. State cancelled? Promptly I opened my English dictionary app.

- So both cancelled and canceled are correct spellings… But which one is our payment provider using?

I looked at the webhook payload: state: "canceled". Went straight to our provider's API documentation. Once again, in the example of the webhook payload: state: "canceled".

- Haskell, that's it. A single l never caused so much trouble. - told my cat as he started snoring.