Philipp H was going through some log files generated by their CI job to try and measure how long certain steps in the process took. He took the obvious path of writing code to read the logfiles, parse out the timestamps, and then take the difference between them.Everything worked fine, until for certain steps, a negative timestamp was reported:
Matthias sends us what he calls the "tern of the century". Which, before I share it with you: bad news, it's just a regular bad ternary. But it remains bad in interesting ways, so it's definitely worth talking about. But let's not oversell it.
Grace was tracking down some production failures, which put her on the path to inspecting a lot of URLs in requests. And that put her onto this blob of code:
Grace sends us, in her words, "the function that validates the data from the signup form for a cursed application."It's more than one function, but there are certainly some clearly cursed aspects of the whole thing.
Today we return to Jessica (previously), who still suffers under Windows Forms. But it's not all Windows Forms. There's also random CLI tools kicking around. CLI tools which should really be designed to run as a service,Let's start with the Main method of this particular tool.
I recognize that our comments system here leaves much to be desired, especially with regards to the spam filter. Lots of good comments get moderated, an annoying quantity of spam gets through. But today, I want to take a moment to talk about some of the spam we get. Because we get a lot. And since most of you never see it as most of it hits our moderation queue, I don't think you can appreciate how weird some of the spam we get is. Formatting preserved, but links- where they were present- stripped.We'll start with one of my "favorites", the sycophant:
Today's anonymous submitter sends us some C# code. This particular block of code controls whether two different columns are visible on the screen. If the field Dist_Por equals one set of constants, we display one column, if it equals a different constant, we display the other. Seems simple enough.My question to you is this: how many nested ternaries do you need to solve this problem?
Doreann has touched this particular function many, many times. In all those times, she never noticed this particular little line, dropped in by a third-party contractor that has long since cashed their check and wandered off to other things.
Thomas worked for a company based in Germany which was looking to expand internationally. Once they started servicing other locales, things started to break. It didn't take long to track the problem down to a very "percise" numeric parser.
Denilson uses a password manager, like one should. Except there was a router which simply would not let the password manager fill the password field. Sure, Denilson could just copy and paste, but the question of why remained.And that meant checking the HTML and JavaScript code the router served up. Just pulling up the dev tools brought up all sorts of "fun" discoveries. For example, the application was built in Vue, a front-end framework. But in addition to using Vue, it also used jQuery for some DOM manipulations. But it didn't just use jQuery. It loaded jquery-3.5.1.slim.min.js directly from its static files. It also loaded vendor.js which also contained the same version of jQuery. At least it was the same version.While browsing, Denilson found a function called reloadOnF5, which raises an interesting question: isn't that just what the browser does anyway?
Sandra from InitAg (previously) tries to keep the team's code quality up. The team she's on uses CI, code reviews, linting and type checking, and most important: hiring qualified people. Overall, the team's been successful recently. Recently.The company got its start doing data-science, which meant much of the initial code was written by brilliant PhDs who didn't know the first thing about writing software. Most of that code has been retired, but it is impossible to dispatch all of it.Which brings us to Stan. Stan was a one-man dev-team/sysadmin for a mission critical piece of software. No one else worked on it, no one else looked at it, but that was "okay" because Stan was happy to work evenings and weekends without anyone even suggesting it. Stan loved his work, perhaps a little too much. And as brilliant as Stan was, when it came to software engineering, he was at best "brillant".Which brings us to a file called utils/file_io.py. As you might gather from the full name there, this is a "utility" module stuffed with "file and IO" related functions. Let's look at a few:
Gretchen wanted to, in development, disable password authentication. Just for a minute, while she was testing things. That's when she found this approach to handling authentication.
Jon supports some software that's been around long enough that the first versions of the software ran on, and I quote, "homegrown OS". They've long since migrated to Linux, and in the process much of their software remained the same. Many of the libraries that make up their application haven't been touched in decades. Because of this, they don't really think too much about how they version libraries; when they deploy they always deploy the file as mylib.so.1.0. Their RPM post-install scriptlet does an ldconfig after each deployment to get the symlinks updated.For those not deep into Linux library management, a brief translation: shared libraries in Linux are .so files. ldconfig is a library manager, which finds the "correct" versions of the libraries you have installed and creates symbolic links to standard locations, so that applications which depend on those libraries can load them.In any case, Jon's team's solution worked until it didn't. They deployed a new version of the software, yum reported success, but the associated services refused to start. This was bad, because this happened in production. It didn't happen in test. They couldn't replicate it anywhere else, actually. So they built a new version of one of the impacted libraries, one with debug symbols enabled, and copied that over. They manually updated the symlinks, instead of using ldconfig, and launched the service.The good news: it worked.The bad news: it worked, but the only difference was that the library was built with debug symbols. The functionality was exactly the same.Well, that was the only difference other than the symlink.Fortunately, a "before" listing of the library files was captured before the debug version was installed, a standard practice by their site-reliability-engineers. They do this any time they try and debug in production, so that they can quickly revert to the previous state. And in this previous version, someone noticed that mylib.so was a symlink pointing to mylib.so.1.0.bkup_20190221.Once again, creating a backup file is a standard practice for their SREs. Apparently, way back in 2019 someone was doing some debugging. They backed up the original library file, but never deleted the backup. And for some reason, ldconfig had been choosing the backup file when scanning for the "correct" version of libraries. Why?Here, Jon does a lot of research for us. It turns out, if you start with the man pages, you don't get a answer- but you do get a warning:
Goodhart's Law states that when a measure becomes a target, it ceases to be a good measure. Or, more to the point: you get what you measure.If, for example, you measure code coverage, you are going to get code coverage. It doesn't mean the tests will be any good, it just means that you'll write tests that exercise different blocks of code.For example, Capybara James sends us this unit test:
It's always good to think through how any given database operation behaves inside of a transaction. For example, Faroguy inherited a Ruby codebase which was mostly db.execute("SOME SQL") without any transactions at all. This caused all sorts of problems with half-finished operations polluting the database.Imagine Faroguy's excitement upon discovering a function called db_trans getting called in a few places. Well, one place, but that's better than none at all. This clearly must mean that at least one operation was running inside of a transaction, right?
A good C programmer can write C in any language, especially C++. A bad C programmer can do the same, and a bad C programmer will do all sorts of terrifying things in the process.Gaetan works with a terrible C programmer.Let's say, for example, you wanted to see if an index existed in an array, and return its value- or return a sentinel value. What you definitely shouldn't do is this:
Arguably, the worst moment for date times was the shift from Julian to Gregorian calendars. The upgrade took a long time, too, as some countries were using the Julian calendar over 300 years from the official changeover, famously featured in the likely aprochryphal story about Russia arriving late for the Olympics.At least that change didn't involve adding any extra months, unlike some of the Julian reforms, which involved adding multiple "intercalary months" to get the year back in sync after missing a pile of leap years.Speaking of adding months, Will J sends us this "calendar" enum:
While I'm not hugely fond of ORMs (I'd argue that relations and objects don't map neatly to each other, and any ORM is going to be a very leaky abstraction for all but trivial cases), that's not because I love writing SQL. I'm a big fan of query-builder tools; describe your query programatically, and have an API that generates the required SQL as a result. This cuts down on developer error, and also hopefully handles all the weird little dialects that every database has.For example, did you know Postgres has an @> operator? It's a contains operation, which returns true if an array, range, or JSON dictionary contains your search term. Basically, an advanced "in" operation.Gretchen's team is using the Knex library, which doesn't have a built-in method for constructing those kinds of queries. But that's fine, because it does offer a whereRaw method, which allows you to supply raw SQL. The nice thing about this is that you can still parameterize your query, and Knex will handle all the fun things, like transforming an array into a string.Or you could just not use that, and write the code yourself:
Antonio has an acquaintance has been seeking career advancement by proactively hunting down and fixing bugs. For example, in one project they were working on, there was a bug where it would incorrectly use MiB for storage sizes instead of MB, and vice-versa.We can set aside conspiracy theories about HDD and RAM manufacturers lying to us about sizes by using MiB in marketing. It isn't relevant, and besides, its not like anyone can afford RAM anymore, with crazy datacenter buildouts. Regardless, which size to use, the base 1024 or base 1000, was configurable by the user, so obviously there was a bug handling that flag. Said acquaintance dug through, and found this:
Henrik H's employer thought they could save money by hiring offshore, and save even more money by hiring offshore junior developers, and save even more money by basically not supervising them at all.Henrik sends us just one representative line:
I've had the misfortune of working in places which did source-control via comments. Like one place which required that, with each section of code changed, you needed to add a comment with your name, the ticket number, and the reason the change was made. You know, the kind of thing you can just get from your source control service.In their defense, that policy was invented for mainframe developers and then extended to everyone else, and their source control system was in Visual Source Safe. VSS was a) terrible, and b) a perennial destroyer of history, so maybe they weren't entirely wrong and VSS was the real WTF. I still hated it.In any case, Alice's team uses more modern source control than that, which is why she's able to explain to us the story of this function:
Industrial machines are generally accompanied by "Human Machine Interfaces", HMIs. This is industrial slang for a little computerized box you use to control the industrial machine. All the key logic and core functionality and especially the safety functionality is handled at a deeper computer layer in the system. The HMI is just buttons users can push to interact with the machine.Purchasers of those pieces of industrial equipment often want to customize that user interface. They want to guide users away from functions they don't need, or make their specific workflow clear, or even just brand the UI. This means that the vendor needs to publish an API for their HMI.Which brings us to Wendy. She works for a manufacturing company which wants to customize the HMI on a piece of industrial equipment in a factory. That means Wendy has been reading the docs and poking at the open-sourced portions of the code, and these raise more questions than they answer.For example, the HMI's API provides its own set of collection types, in C#. We can wonder why they'd do such a thing, which is certainly a WTF in itself, but this representative line raises even more questions than that:
Python is (in)famous for its "batteries included" approach to a standard library, but it's not that notable that it has plenty of standard data structures, like dicts. Nor is in surprising that dicts have all sorts of useful methods, like pop, which removes a key from the dict and returns its value.Because you're here, reading this site, you'll also be unsurprised that this doesn't stop developers from re-implementing that built-in function, badly. Karen sends us this:
Agatha has inherited some Windows Forms code. This particular batch of such code falls into that delightful category of code that's wrong in multiple ways, multiple times. The task here is to disable a few panels worth of controls, based on a condition. Or, since this is in Spanish, "bloquear controles". Let's see how they did it.
Today's snippet from Rich D is short and sweet, and admittedly, not the most TFs of WTFs out there. But it made me chuckle, and sometimes that's all we need. This Java snippet shows us how to delete a file:
We mostly don't pick on bad SQL queries here, because mostly the query optimizer is going to fix whatever is wrong, and the sad reality is that databases are hard to change once they're running; especially legacy databases. But sometimes the code is just so hamster-bowling-backwards that it's worth looking into.Jim J has been working on a codebase for about 18 months. It's a big, sprawling, messy project, and it has code like this:
Every once in awhile, we get a bit of terrible code, and our submitter also shares, "this isn't called anywhere," which is good, but also bad. Ernesto sends us a function which is called in only one place:
Aankhen has a peer who loves writing Python scripts to automate repetitive tasks. We'll call this person Ernest.Ernest was pretty proud of some helpers he wrote to help him manage his Docker containers. For example, when he wanted to stop and remove all his running Docker containers, he wrote this script:
Dana sends us a WTF that'll turn your head. She was shopping for new hard drives, and was doing it from her phone, a fairly reasonable tool to use for online shopping these days. She opened the website of one vendor, and it was rotated 90 degrees. Or half-pi radians, for those of us that are more used to sensible units.This was irrespective of any rotation settings on her phone, the website insisted on showing itself in landscape mode. This created quite the unusual appearance when she held her phone in portrait orientation: the browser chrome surrounding the content was in portrait mode, but the page itself was in landscape.Obviously, this is a terrible design choice. But Dana wanted to know more. So she started digging in. There was no sign of this behavior on a desktop, which sure, I'd hope not. Attempting to use wget to download the page caused a 403. Using curl downloaded a JavaScript challenge. Fine, they didn't want bots, but Dana wasn't a bot.Poking around in the network tab of the desktop browser's debugging tools helped Dana learn a few things. First: the line endings in the files were all CRLF, implying that all development happened on Windows machines. Maybe that's not interesting, but in 2026, it feels unusual. Second, the page is setting a PHPSESSID cookie, so clearly the backend is written in PHP. But most important, Dana is able to piece together what she needs to successfully use curl to download the page, once pretending to be a desktop browser, and once pretending to be a mobile browser. With that, she ran a diff to see what changed.The desktop version started with 42 blank lines. The mobile version started with 41. The rest of the pages were substantially the same, with two exceptions. First, the mobile page also added a stylesheet called stylesheet-responsive.css. I assume that name was chosen because irony is dead; nothing about this site is responsive. Second, there was a subtle difference in the body tags.You see, both pages had a body tag like this:
Capybara James sends us some code which is totally designed to be modular.This particular software accepts many kinds of requests which it then converts into a request for a ListView. This is a perfect example of where to use polymorphism, so you can write one transform method that operates on any kind of request.Let's see how they did it:
Today's anonymous submitter passes us a single line of JavaScript, and it's a doozy. This line works, but that's through no fault of the developer behind it.
It is eminently reasonable for companies to have "readability standards" for their code. You're writing this code for humans to read, after all, at least in theory. You need to communicate to future inheritors of your code.But that doesn't mean readability standards are good. Tony's company, for example, has rules about returning boolean values from functions, and those rules mean you are expected to write code like this:
Today, it's not exactly the code that was bad. For some time, a government agency had been collecting information from users using fillable PDF forms. The user would submit the form, and then a data entry clerk would copy the text from the form into a database. This, of course, raised the question: why was someone manually riding the copy/paste button?Sally was tasked with automating this. The data is already in a digital format, so it should be easy to use a PDF library to parse out the entered data and insert it into the database. And it almost was.Sally shares with us, not code, but the output of her program which scanned the fields, looking for their names:
A few holiday seasons ago, Paul S was doing the requisite holiday shopping online, looking for those perfectly impersonal but mildly thoughtful gifts that many companies specialize in. This was one of the larger such vendors, well known for its fruit-filled gift baskets. As is not uncommon for our readers, when the site started misbehaving, he pulled up the dev tools. He didn't solve the problem, but he did learn a lot about how they were managing their API keys, as this was exposed to the client: