The non-equal string
We have a workflow where the user invites another user to the platform. He sets in a form, a temporary identifier and then the app sends an email with a unique url. The invited user has to go to the generated url and complete a form with the secret identifier to enter. So far so good.
We got a report from a user that the flow doesn't work. The specs hasn't broken, nobody has touched this code for awhile so our QA team start doing some manual tests for the flow. Nothing seems wrong so a developer (me) started to investigate the issue. I checked the identifier of the user and it was correct in the database. I launch a rails console and I see the following:
Ok now the fun begins. Why these two strings aren't equal? I tried different commands like p
and print
but everything showed the same output. I am lucky and these two are numbers, so I could try methods like .to_i
and .to_d
. With these methods I got 0 and 0.0 accordingly for the first string which it is the identifier that the user input set in the initial form (for the other in the params, I got the right number).
It seemed like the user has input something that wasn't correct. I tried .split("")
and voila! It revealed two extra characters in the beginning and in the end of the string. It appears that the user has done some copy-paste from somewhere and it transferred two special characters which wasn't visible. But in the string comparison it mattered. Sherlock Holmes investigation ended. Lesson from this: Sincerely I don't know. Should we do more strict validation of the user input so he won't be able to add non-visible characters? Probably, but we still haven't decided.
The immortal users
We have users and they have many tasks (a task has only one user so it has a user_id
on it). For some business reasons we don't want to delete tasks, just to nullify the user_id
on them. One day we suddenly started getting errors that a user can't be destroyed. It was getting a foreign_key violation constraint from the postgres database to the association with the task. We start investigating what is happening...
We get the user's records and do some investigation. We managed to reproduce the issue in the development which is a good thing. Indeed the user couldn't be deleted even though we were deleting the tasks entirely.
The problem was simple: We had a memory overflow a couple days ago. In a query, there was included the tasks with another field which was nil. We didn't want to query this extra records with nil field. So we had to add something like: .where.not(the_field: nil)
in a scope and in many places.
The developer decided instead of adding this new scope in many places and for securing that this issue won't happen by accident again, to add a default_scope. Can you imagine now the issue above? The immortal user had tasks both with this extra_field as nil and not nil. The result was that the nullify didn't nullified the user_id with the records of the extra_field nil because of the extra scope.
The funny thing is that the first developer who investigated it, deleted the tasks of the user with plain sql query instead of activerecord ORM. This had as a result to delete manually all the tasks and then be able to kill the immortal user. The result added in confusion so we had to try again. After a second examination and using the normal workflow, we managed to see the queries in the activerecord flow and clearly see the issue with the default_scope. So lesson from this: Don't use default_scope and alway try the normal workflow.
Did you had any crazy bugs like the above? Send me yours! Or send me any ideas about how you prevent difficult to catch bugs like the above.