The Daily WTF
The following are the titles of recent articles syndicated from The Daily WTF
Add this feed to your friends list for news aggregation, or view this feed's syndication information.
LJ.Rossia.org makes no claim to the content supplied through this journal account. Articles are retrieved via a public feed supplied by the site for this purpose.
[ << Previous 20 ]
Monday, June 23rd, 2025 | LJ.Rossia.org makes no claim to the content supplied through this journal account. Articles are retrieved via a public feed supplied by the site for this purpose. |
6:30 am |
Classic WTF: Take the Bus It's summer break time, here at TDWTF, and based on this classic, we shouldn't be traveling by bus. Original --Remy
Rachel started working as a web developer for the local bus company. The job made her feel young, since the buses, the IT infrastructure, and most of their back-office code was older than she was. The bus fare-boxes were cash only, and while you could buy a monthly pass, it was just a little cardboard slip that you showed the driver. Their accounting system ran on a mainframe, their garage management software was a 16-bit DOS application. Email ran on an Exchange 5.5 server.

In charge of all of the computing systems, from the web to DOS, was Virgil, the IT director. Virgil had been hired back when the accounting mainframe was installed, and had nestled into his IT director position like a tick. The bus company, like many such companies in the US, was ostensibly a private company, but chartered and subsidized by the city. This created a system which had all the worst parts of private-sector and public-sector employment merged together, and Virgil was the master of that system.
Rachel getting hired on was one of his rare “losses”, and he wasn’t shy about telling her so.
“I’ve been doing the web page for years,” Virgil said. “It has a hit counter, so you can see how many hits it actually gets- maybe 1 or 2 a week. But management says we need to have someone dedicated to the website.” He grumbled. “Your salary is coming out of my budget, you know.”
That website was a FrontPage 2000 site, and the hit-counter was broken in any browser that didn’t have ActiveX enabled. Rachel easily proved that there was far more traffic than claimed, not that there was a lot. And why should there be? You couldn’t buy a monthly pass online, so the only feature was the ability to download PDFs of the hand-schedules.
With no support, Rachel did her best to push things forward. She redesigned the site to be responsive. She convinced the guy who maintained their bus routes (in a pile of Excel spreadsheets) to give her regular exports of the data, so she could put the schedules online in a usable fashion. Virgil constantly grumbled about wasting money on a website nobody used, but as she made improvements, more people started using it.
Then it was election season. The incumbent mayor had been complaining about the poor service the bus company was offering, the lack of routes, the costs, the schedules. His answer was, “cut their funding”. Management started talking about belt-tightening, Virgil started dropping hints that Rachel was on the chopping block, and she took the hint and started getting resumes out.
A miracle occurred. The incumbent mayor’s campaign went off the rails. He got caught siphoning money from the city to pay for private trips. A few local cops mentioned that they’d been called in to cover-up the mayor’s frequent DUIs. His re-election campaign’s finances show strange discrepancies, and money had come in that couldn’t be tied back to a legitimate contribution. He tried to get a newly built stadium named after himself, which wasn’t illegal, but was in poor taste and was the final straw. He dropped out of the election, paving the way for “Mayor Fred” to take over.
Mayor Fred was a cool Mayor. He wanted to put in bike lanes. He wanted to be called “Mayor Fred”. He wanted to make it easier for food trucks to operate in the city. And while he shared his predecessor’s complaints about the poor service from the bus company, he had a different solution, which he revealed while taking a tour of the bus company’s offices.
“I’m working right now to secure federal grants, private sector funding, to fund a modernization project,” Mayor Fred said, grinning from behind a lectern. “Did you know we’re paying more to keep our old buses on the road for five years than it would cost to buy new buses?” And thus, Mayor Fred made promises. Promises about new buses, promises about top-flight consultants helping them plan better routes, promises about online functionality.
Promises that made Virgil grumble and whine. Promises that the mayor… actually kept.
New buses started to hit the streets. They had GPS and a radio communication system that gave them up-to-the-second location reporting. Rachel got put in charge of putting that data on the web, with a public API, and tying it to their schedules. A group of consultants swung through to help, and when the dust settled, Rachel’s title was suddenly “senior web developer” and she was in charge of a team of 6 people, integrating new functionality to the website.
Virgil made his opinion on this subject clear to her: “You are eating into my budget!”
“Isn’t your budget way larger?” Rachel asked.
“Yes, but there’s so much more to spend it on! We’re a bus company, we should be focused on getting people moving, not giving them pretty websites with maps that tell them where the buses are! And now there’s that new FlashCard project!”
FlashCard was a big project that didn’t involve Rachel very much. Instead of cash fares and cardboard passes, they were going to get an RFID system. You could fill your card at one of the many kiosks around the city, or even online. “Online” of course, put it in Rachel’s domain, but it was mostly a packaged product. Virgil, of all people, had taken over the install and configuration, Rachel just customized the stylesheet so that it looked vaguely like their main site.
Rachel wasn’t only an employee of the bus company, she was also a customer. She was one of the first in line to get a FlashCard. For a few weeks, it was the height of convenience. The stop she usually needed had a kiosk, she just waved her card at the farebox and paid. And then, one day, when her card was mostly empty and she wasn’t anywhere near a kiosk, she decided to try filling her card online.
Thank you for your purchase. Your transaction will be processed within 72 hours.
That was a puzzle. The kiosks completed the transaction instantly. Why on Earth would a website take 3 days to do the same thing? Rachel became more annoyed when she realized she didn’t have enough on her card to catch the bus, and she needed to trudge a few blocks out of her way to refill the card. That’s when it started raining. And then she missed her bus, and had to wait 30 minutes for the next one. Which is when the rain escalated to a downpour. Which made the next bus 20 minutes late.
Wet, cold, and angry, Rachel resolved to figure out what the heck was going on. When she confronted Virgil about it, he said, “That’s just how it works. I’ve got somebody working full time on keeping that system running, and that’s the best they can do.”
Somebody working full time? “Who? What? Do you need help? I’ve done ecommerce before, I can-”
“Oh no, you’ve already got your little website thing,” Virgil said. “I’m not going to let you try and stage a coup over this.”
With an invitation like that, Rachel decided to figure out what was going on. It wasn’t hard to get into the administration features of the FlashCard website. From there, it was easy to see the status of the ecommerce plugin for processing transactions: “Not installed”. In fact, there was no sign at all that the system could even process transactions at all.
The only hint that Rachel caught was the configuration of the log files. They were getting dumped to /dev/lp1 . A printer. Next came a game of hide-and-seek- the server running the FlashCard software wasn’t in their tiny data-center, which meant she had to infer its location based on which routers were between her and it. It took a few days of poking around their offices, but she eventually found it in the basement, in an office.
In that office was one man with coke-bottle glasses, an antique continuous feed printer, a red document shredder, and a FlashCard kiosk running in diagnostic mode. “Um… can I help you?” the man asked.
“Maybe? I’m trying to track down how we’re processing credit card transactions for the FlashCard system?”
The printer coughed to life, spilling out a new line. “Well, you’re just in time then. Here’s the process.” He adjusted his glasses and peered at the output from the printer:
TRANSACTION CONFIRMED: f6ba779d22d5;4012888888881881;$25.00
The man then kicked his rolly-chair over to the kiosk. The first number was the FlashCard the transaction was for, the second was the credit card number, and the third was the amount. He punched those into the kiosk’s keypad, and then hit enter.
“When it gets busy, I get real backed up,” he confessed. “But it’s quiet right now.”
Rachel tracked down Virgil, and demanded to know what he thought he was doing.
“What? It’s not like anybody wants to use a website to buy things,” Virgil said. “And if we bought the ecommerce module, the vendor would have charged us $2,000/mo, on top of an additional transaction fee. This is cheaper, and I barely have enough room in my budget as it is!”
[Advertisement] Plan Your .NET 9 Migration with ConfidenceYour journey to .NET 9 is more than just one decision.Avoid migration migraines with the advice in this free guide. Download Free Guide Now!
| Friday, June 20th, 2025 | LJ.Rossia.org makes no claim to the content supplied through this journal account. Articles are retrieved via a public feed supplied by the site for this purpose. |
9:00 am |
Error'd: Colophony Just a quick note this week: I discovered that many people have been sending in submissions for this column and designating them for CodeSod by mistakes. Consequently, there is an immense backlog of material from which to choose. An abundance of riches! We will be seeing some older items in the future. For today, a collection of colons:
Bill NoLastName
, giving away clues to his banking security questions online:
"If had known there was a limit, I would have changed my daughter's
middle name. I've been caught by this before - my dad has only a
middle initial (no middle name)."
Gordon F.
heard of a greal deal:
"This is the first mention of shipping on a hearing aids website. Tough choice."
Michael P.
underlines a creative choice:
"I got an email from a recruiter about a job opening. I'm a little confused about the requirements."
Cole T.
pretend panics about pennies (and maybe we need an article about false urgency, hm):
"Oh no! My $0 in rewards are about to expire!"
Finally, bibliophile
WeaponizedFun (alsonolastname)
humblebrags erudition. It ain't War & Peace, but it's still an ordeal!
"After recently finishing The Brothers Karamazov after 33 hours on audio disc, I was a bit surprised to see that Goodreads is listing this as my longest book with only 28 pages. 28 discs, maybe, but I still am questioning their algorithm, because this just looks silly."
| Thursday, June 19th, 2025 | LJ.Rossia.org makes no claim to the content supplied through this journal account. Articles are retrieved via a public feed supplied by the site for this purpose. |
6:30 am |
CodeSOD: Using the Old Bean If you write a lot of Java, you're going to end up writing a lot of getters and setters. Without debating the merits of loads of getters and setters versus bare properties, ideally, getters and setters are the easiest code to write. Many IDEs will just generate them for you! How can you screw up getters and setters?
Well, Dave found someone who could.
private ReportDatesDao reportDatesDao;
@Resource(name = CensusDao.BEAN_NAME)
public void setAuditDao(CensusDao censusDao) {
this.reportDatesDao = reportDatesDao;
}
The function is called setAuditDao , takes a CensusDao input, but manipulates reportDatesDao , because clearly someone copy/pasted and didn't think about what they were doing.
The result, however, is that this just sets this.reportDatesDao equal to itself.
I'm always impressed by code which given the chance to make multiple decisions makes every wrong choice, even if it is just lazy copy/paste.
[Advertisement] Plan Your .NET 9 Migration with ConfidenceYour journey to .NET 9 is more than just one decision.Avoid migration migraines with the advice in this free guide. Download Free Guide Now!
| Wednesday, June 18th, 2025 | LJ.Rossia.org makes no claim to the content supplied through this journal account. Articles are retrieved via a public feed supplied by the site for this purpose. |
6:30 am |
CodeSOD: Stop Being So #### Many a network admin has turned to the siren song of Perl to help them automate managing their networks. Frank's predecessor is no exception.
They also got a bit combative about people critiquing their Perl code:
$Subnets = @("0.0.0.0","128.0.0.0","192.0.0.0","224.0.0.0","240.0.0.0","248.0.0.0","252.0.0.0","254.0.0.0","255.0.0.0","255.128.0.0","255.192.0.0","255.224.0.0","255.240.0.0","255.248.0.0","255.252.0.0","255.254.0.0","255.255.0.0","255.255.128.0","255.255.192.0","255.255.224.0","255.255.240.0","255.255.248.0","255.255.252.0","255.255.254.0","255.255.255.0","255.255.255.128","255.255.255.192","255.255.255.224","255.255.255.240","255.255.255.248","255.255.255.252","255.255.255.254","255.255.255.255")
I believe them when they say that the lookup array is faster, but it leaves me wondering: what are they doing where performance matters that much?
I don't actually think this ascends to the level of a WTF, but I do think the defensive comment is funny. Clearly, the original developer was having a time with people complaining about it.
Frank notes that while Perl has a reputation as a "write only language," this particular set of scripts was actually quite easy to read and maintain. So yes, I guess we should stop being so #### about it.
[Advertisement] Plan Your .NET 9 Migration with ConfidenceYour journey to .NET 9 is more than just one decision.Avoid migration migraines with the advice in this free guide. Download Free Guide Now!
| Tuesday, June 17th, 2025 | LJ.Rossia.org makes no claim to the content supplied through this journal account. Articles are retrieved via a public feed supplied by the site for this purpose. |
6:30 am |
CodeSOD: A Second Date Ah, bad date handling. We've all seen it. We all know it. So when Lorenzo sent us this C# function, we almost ignored it:
private string GetTimeStamp(DateTime param)
{
string retDate = param.Year.ToString() + "-";
if (param.Month < 10)
retDate = retDate + "0" + param.Month.ToString() + "-";
else
retDate = retDate + param.Month.ToString() + "-";
if (param.Day < 10)
retDate = retDate + "0" + param.Day.ToString() + " ";
else
retDate = retDate + param.Day.ToString() + " ";
if (param.Hour < 10)
retDate = retDate + "0" + param.Hour.ToString() + ":";
else
retDate = retDate + param.Hour.ToString() + ":";
if (param.Minute < 10)
retDate = retDate + "0" + param.Minute.ToString() + ":";
else
retDate = retDate + param.Minute.ToString() + ":";
if (param.Second < 10)
retDate = retDate + "0" + param.Second.ToString() + ".";
else
retDate = retDate + param.Second.ToString() + ".";
if (param.Millisecond < 10)
retDate = retDate + "0" + param.Millisecond.ToString();
else
retDate = retDate + param.Millisecond.ToString();
return retDate;
}
Most of this function isn't terribly exciting. We've seen this kind of bad code before, but even when we see a repeat like this, there are still special treats in it. Look at the section for handling milliseconds: if the number is less than 10, they pad it with a leading zero. Just the one, though. One leading zero should be enough for everybody.
But that's not the thing that makes this code special. You see, there's another function worth looking at:
private string FileTimeStamp(DateTime param)
{
string retDate = param.Year.ToString() + "-";
if (param.Month < 10)
retDate = retDate + "0" + param.Month.ToString() + "-";
else
retDate = retDate + param.Month.ToString() + "-";
if (param.Day < 10)
retDate = retDate + "0" + param.Day.ToString() + " ";
else
retDate = retDate + param.Day.ToString() + " ";
if (param.Hour < 10)
retDate = retDate + "0" + param.Hour.ToString() + ":";
else
retDate = retDate + param.Hour.ToString() + ":";
if (param.Minute < 10)
retDate = retDate + "0" + param.Minute.ToString() + ":";
else
retDate = retDate + param.Minute.ToString() + ":";
if (param.Second < 10)
retDate = retDate + "0" + param.Second.ToString() + ".";
else
retDate = retDate + param.Second.ToString() + ".";
if (param.Millisecond < 10)
retDate = retDate + "0" + param.Millisecond.ToString();
else
retDate = retDate + param.Millisecond.ToString();
return retDate;
}
Not only did they fail to learn the built-in functions for formatting dates, they forgot about the functions they wrote for formatting dates, and just wrote (or realistically, copy/pasted?) the same function twice.
At least both versions have the same bug with milliseconds. I don't know if I could handle it if they were inconsistent about that.
| Monday, June 16th, 2025 | LJ.Rossia.org makes no claim to the content supplied through this journal account. Articles are retrieved via a public feed supplied by the site for this purpose. |
6:30 am |
CodeSOD: The Firefox Fix Yitzchak was going through some old web code, and found some still in-use JavaScript to handle compatibility issues with older Firefox versions.
if ($.browser.mozilla &&
$.browser.version.slice(0, 1) == '1')
{
…
}
What a marvel. Using JQuery, they check which browser is reported- I suspect JQuery is grabbing this from the user-agent string- and then its version. And if the version has a 1 in its first digit, we apply a "fix" for "compatibility".
I guess it's a good thing there will never be more than 9 versions of Firefox. I mean, what version are they on now? Surely the version number doesn't start with a "1", nor has it started with a "1" for some time, right?
 [Advertisement]
Keep all your packages and Docker containers in one place, scan for vulnerabilities, and control who can access different feeds. ProGet installs in minutes and has a powerful free version with a lot of great features that you can upgrade when ready. Learn more.
| Friday, June 13th, 2025 | LJ.Rossia.org makes no claim to the content supplied through this journal account. Articles are retrieved via a public feed supplied by the site for this purpose. |
6:30 am |
Error'd: Squaring the Circle
Time Lord
Jason H.
has lost control of his calendar.
"This is from my credit card company. A major company you have definitely
heard of and depending upon the size of the area you live in, they
may even have a bank branch near you. I've reloaded the page and
clicked the sort button multiple times to order the rows by date
in both ascending and descending order. It always ends up the same.
May 17th and 18th happened twice, but not in the expected order."
I must say that it is more fun when we know who they are.
A job hunter with the unlikely appelation
full_name
suggested titling this "[submission_title]" which seems appropriate.
"The browser wars continue to fall out in HTML email," reports
Ben S.
"Looking at the source code of this email, it was evidently written by & for Microsoft products (including <center> tags!), and the author likely never saw the non-Microsoft version I'm seeing where only a haphazard assortment of the links are styled. But that doesn't explain why it's AN ELEVEN POINT SCALE arranged in a GRID."
"The owl knows who you are," sagely stated
Jan.
"This happens when you follow someone back. I love how I didn't
have to anonymize anything in the screenshot."
"Location, location, location!" crows
Tim K.
who is definitely not a Time Lord.
"Snarky snippet: Found while cleaning up miscellaneous accounts
held by a former employee. By now we all know to expect how these
lists are sorted, but what kind of sadist *created* it?
Longer explanation: I wasn't sure what screenshot to send
with this one, it just makes less and less sense the more I
look at it, and no single segment of the list contains all of
the treasures it hides. "America" seems to refer to the entire
western hemisphere, but from there we either drill down directly
to a city, or sometimes to a US state, then a city, or
sometimes just to a country. The only context that indicates
we're talking about Jamaica the island rather than Jamaica, NY
is the timezone listed, assuming we can even trust those.
Also, that differentiator only works during DST. There are eight
entries for Indiana. There are TEN entries for the Antarctic."
Well.
In this case, there is a perfectly good explanation. TRWTF
is time zones, that's all there is to it. These are the
official IANA names as recorded in the public TZDB.
In other words, this list wasn't concocted by a mere sadist, oh no.
This list was cooked up by an entire committee! If you have the
courage, you can learn more than you ever wanted to know about time
at the
IANA time zones website
 [Advertisement]
Keep the plebs out of prod. Restrict NuGet feed privileges with ProGet. Learn more.
| Thursday, June 12th, 2025 | LJ.Rossia.org makes no claim to the content supplied through this journal account. Articles are retrieved via a public feed supplied by the site for this purpose. |
6:30 am |
CodeSOD: Gridding My Teeth Dan's co-workers like passing around TDWTF stories, mostly because seeing code worse than what they're writing makes them feel less bad about how often they end up hacking things together.
One day, a co-worker told Dan: "Hey, I think I found something for that website with the bad code stories!"
Dan's heart sank. He didn't really want to shame any of his co-workers. Fortunately, the source-control history put the blame squarely on someone who didn't work there any more, so he felt better about submitting it.
This is another ASP .Net page, and this one made heavy use of GridView elements. GridView controls applied the logic of UI controls to generating a table. They had a page which contained six of these controls, defined like this:
<asp:GridView ID="gvTaskMonth1" runat="server" CssClass="leadsGridView" AutoGenerateColumns="False" OnRowDataBound="gvTaskMonth1_RowDataBound"> ... </asp:GridView>
<asp:GridView ID="gvTaskMonth2" runat="server" CssClass="leadsGridView" AutoGenerateColumns="False" OnRowDataBound="gvTaskMonth1_RowDataBound"> ... </asp:GridView>
<asp:GridView ID="gvTaskMonth3" runat="server" CssClass="leadsGridView" AutoGenerateColumns="False" OnRowDataBound="gvTaskMonth1_RowDataBound"> ... </asp:GridView>
The purpose of this screen was to display a roadmap of coming tasks, broken up by how many months in the future they were. The first thing that leaps out to me is that they all use the same event handler for binding data to the table, which isn't in-and-of-itself a problem, but the naming of it is certainly a recipe for confusion.
Now, to bind these controls to the data, there needed to be some code in the code-behind of this view which handled that. That's where the WTF lurks:
private void CreateRoadmap()
{
for (int i = 1; i < 7; i++)
{
switch (i)
{
case 1:
if (gvTaskMonth1.Rows.Count > 0)
{
InsertTasks(gvTaskMonth1, DateTime.Parse(txtDatePeriod1.Text), "1");
}
break;
case 2:
if (gvTaskMonth2.Rows.Count > 0)
{
InsertTasks(gvTaskMonth2, DateTime.Parse(txtDatePeriod2.Text), "2");
}
break;
case 3:
if (gvTaskMonth3.Rows.Count > 0)
{
InsertTasks(gvTaskMonth3, DateTime.Parse(txtDatePeriod3.Text), "3");
}
break;
case 4:
if (gvTaskMonth4.Rows.Count > 0)
{
InsertTasks(gvTaskMonth4, DateTime.Parse(txtDatePeriod4.Text), "4");
}
break;
case 5:
if (gvTaskMonth5.Rows.Count > 0)
{
InsertTasks(gvTaskMonth5, DateTime.Parse(txtDatePeriod5.Text), "5");
}
break;
case 6:
if (gvTaskMonth6.Rows.Count > 0)
{
InsertTasks(gvTaskMonth6, DateTime.Parse(txtDatePeriod6.Text), "6");
}
break;
}
}
}
Ah, the good old fashioned loop-switch sequence anti-pattern. I understand the motivation: "I want to do the same thing for six different controls, so I should use a loop to not repeat myself," but then couldn't quite figure out how to do that, so they just repeated themselves, but inside of a loop.
The "fix" was to replace all of this with something more compact:
private void CreateRoadmap()
{
InsertTasks(gvTaskMonth1, DateTime.Parse(txtDatePeriod1.Text), "1");
InsertTasks(gvTaskMonth2, DateTime.Parse(txtDatePeriod2.Text), "2");
InsertTasks(gvTaskMonth3, DateTime.Parse(txtDatePeriod3.Text), "3");
InsertTasks(gvTaskMonth4, DateTime.Parse(txtDatePeriod4.Text), "4");
InsertTasks(gvTaskMonth5, DateTime.Parse(txtDatePeriod5.Text), "5");
InsertTasks(gvTaskMonth6, DateTime.Parse(txtDatePeriod6.Text), "6");
}
That said, I'd recommend not trying to parse date times inside of a text box inside of this method, but that's just me. Bubbling up the inevitable FormatException that this will generate is going to be a giant nuisance. It's likely that they've got a validator somewhere, so it's probably fine- I just don't like it.
 [Advertisement]
Keep the plebs out of prod. Restrict NuGet feed privileges with ProGet. Learn more.
| Wednesday, June 11th, 2025 | LJ.Rossia.org makes no claim to the content supplied through this journal account. Articles are retrieved via a public feed supplied by the site for this purpose. |
6:30 am |
Credit Card Sins Our anonymous submitter, whom we'll call Carmen, embarked on her IT career with an up-and-coming firm that developed and managed eCommerce websites for their clients. After her new boss Russell walked her around the small office and introduced her to a handful of coworkers, he led her back to his desk to discuss her first project. Carmen brought her laptop along and sat down across from Russell, poised to take notes.
Russell explained that their newest client, Sharon, taught CPR classes. She wanted her customers to be able to pay and sign up for classes online. She also wanted the ability to charge customers a fee in case they cancelled on her.

"You're gonna build a static site to handle all this," he said.
Carmen nodded along as she typed out notes in a text file.
"Now, Sharon doesn't want to pay more than a few hundred dollars for the site," Russell continued, "so we're not gonna hook up an endpoint to use a service-provided API for payments."
Carmen glanced up from her laptop, perplexed. "How are we gonna do it, then?"
"Via email," Russell replied smoothly. "The customer will enter their CC info into basic form fields. When they click Submit, you're gonna send all that to Sharon's business address, and also CC it to yourself for backup and recovery purposes."
Carmen's jaw dropped. "Just ... straight-up email raw credit card data?"
"Yep!" Russell replied. "Sharon knows to expect the emails."
Her heart racing with panic, Carmen desperately cast about for some way for this to be less awful. "Couldn't ... couldn't we at least encrypt the CC info before we send it to her?"
"She's not paying us for that," Russell dismissed. "This'll be easier to implement, anyway! You can handle it, can't you?"
"Yyyes—"
"Great! Go get started, let me know if you have any more questions."
Carmen had plenty of questions and even more misgivings, but she'd clearly be wasting her time if she tried to bring them up. There was no higher boss to appeal to, no coworkers she knew well enough who could slip an alternate suggestion into Russell's ear on her behalf. She had no choice but to swallow her good intentions and implement it exactly the way Russell wanted it. Carmen set up the copied emails to forward automatically to a special folder so that she'd never have to look at them. She cringed every time a new one came in, reflecting on how lucky Sharon and her customers were that the woman supporting her website had a conscience.
And then one day, a thought came to Carmen that really scared her: in how many places, in how many unbelievable ways, was her sensitive data being treated like this?
Eventually, Carmen moved on to bigger and better things. Her first project most likely rests in the hands of Russell's newest hire. We can only hope it's an honest hire.
 [Advertisement]
BuildMaster allows you to create a self-service release management platform that allows different teams to manage their applications. Explore how!
| Tuesday, June 10th, 2025 | LJ.Rossia.org makes no claim to the content supplied through this journal account. Articles are retrieved via a public feed supplied by the site for this purpose. |
6:30 am |
CodeSOD: The Pirate's Code We've talked about ASP .Net WebForms in the past. In this style of development, everything was event driven: click a button, and the browser sends an HTTP request to the server which triggers a series of events, including a "Button Click" event, and renders a new page.
When ASP .Net launched, one of the "features" was a lazy repaint in browsers which supported it (aka, Internet Explorer), where you'd click the button, the page would render on the server, download, and then the browser would repaint only the changed areas, making it feel more like a desktop application, albeit a laggy one.
This model didn't translate super naturally to AJAX style calls, where JavaScript updated only portions of the page. The .Net team added some hooks for it- special "AJAX enabled" controls, as well as helper functions, like __doPostBack , in the UI to generate URLs for "postbacks" to trigger server side execution. A postback is just a POST request with .NET specific state data in the body.
All this said, Chris maintains a booking system for a boat rental company. Specifically, he's a developer at a company which the boat rental company hires to maintain their site. The original developer left behind a barnacle covered mess of tangled lines and rotting hull.
Let's start with the view ASPX definition:
<script>
function btnSave_Click()
{
if (someCondition)
{
javascript:<%#getPostBack()%>;
}
else
{
return false;
}
}
</script>
<html>
<body>
<input type="button" value=" Save Booking " id="btnSave" class="button" title="Save [Alt]" onclick="btnSave_Click()" />
</body>
</html>
__doPostBack is the .NET method for generating URLs for performing postbacks, and specifically, it populates two request fields: __EVENTTARGET (the ID of the UI element triggering the event) and __EVENTARGUMENT , an arbitrary field for your use. I assume getPostBack() is a helper method which calls that. The code in btnSave_Click is as submitted, and I think our submitter may have mangled it a bit in "trimming", but I can see the goal is to ensure than when the onclick event fires, we perform a "postback" operation with some hard-coded values for __EVENTTARGET and __EVENTELEMENT .
Or maybe it isn't mangled, and this code just doesn't work?
I enjoy that the tool-tip "title" field specifies that it's "[Alt]" text, and that the name of the button includes extra whitespace to ensure that it's padded out to a good rendering size, instead of using CSS.
But we can skip past this into the real meat. How this gets handled on the server side:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Page.IsPostBack Then
Dim eventArg As String = Request("__EVENTARGUMENT")
Dim offset As Integer = eventArg.IndexOf("@@@@@")
If (offset > -1) Then
Save()
End If
End If
End Sub
From this, I conclude that getPostBack populates the __EVENTARGUMENT field with a pile of "@", and we use that to recognize that the save button was clicked. Except, and this is the important thing, if they populated the ID property with btnSave , then ASP .Net would automatically call btnSave_Click . The entire point of the __doPostBack functionality is that it hooks into the event handling pattern and acts just like any other postback, but lets you have JavaScript execute as part of sending the request.
The entire application is a boat with multiple holes in it; it's taking on water and going down, and like a good captain, Chris is absolutely not going down with it and looking for a lifeboat.
Chris writes:
The thing in its entirety is probably one of the biggest WTFs I've ever had to work with.
I've held off submitting because nothing was ever straight forward enough to be understood without posting the entire website.
Honestly, I'm still not sure I understand it, but I do hate it.
 [Advertisement]
BuildMaster allows you to create a self-service release management platform that allows different teams to manage their applications. Explore how!
| Monday, June 9th, 2025 | LJ.Rossia.org makes no claim to the content supplied through this journal account. Articles are retrieved via a public feed supplied by the site for this purpose. |
6:30 am |
CodeSOD: A Real POS Report Eddie's company hired a Highly Paid Consultant to help them retool their systems for a major upgrade. Of course, the HPC needed more and more time, and the project ran later and later and ended up wildly over budget, so the HPC had to be released, and Eddie inherited the code.
What followed was a massive crunch to try and hit absolutely hard delivery dates. Management didn't want their team "rewriting" the expensive code they'd already paid for, they just wanted "quick fixes" to get it live. Obviously, the HPC's code must be better than theirs, right?
After release, a problem appeared in one of their sales related reports. The point-of-sale report was meant to deliver a report about which items were available at any given retail outlet, in addition to sales figures. Because their business dealt in a high volume of seasonal items, every quarter the list of items was expected to change regularly.
The users weren't seeing the new items appear in the report. This didn't make very much sense- it was a report. The data was in the database. The report was driven by a view, also in the database, which clearly was returning the correct values? So the bug must be in the code which generated the report…
If POSItemDesc = "Large Sign" Then
grdResults.Columns.FromKey("FColumn12").Header.Caption = "Large Sign"
End If
If POSItemDesc = "Small Sign" Then
grdResults.Columns.FromKey("FColumn12").Header.Caption = "Small Sign"
End If
If POSItemDesc = "2x2 Hanging Sign" Then
grdResults.Columns.FromKey("FColumn12").Header.Caption = "2x2 Hanging Sign"
End If
If POSItemDesc = "1x1 Sign" Then
grdResults.Columns.FromKey("FColumn12").Header.Caption = "1x1 Sign"
End If
If POSItemDesc = "Light Thief" Then
grdResults.Columns.FromKey("FColumn12").Header.Caption = "Light Thief"
End If
If POSItemDesc = "Door Strike" Then
grdResults.Columns.FromKey("FColumn12").Header.Caption = "Door Strike"
End If
First, it's worth noting that inside of the results grid display item, the HPC named the field FColumn12 , which is such a wonderfully self documenting name, I'm surprised we aren't all using that everywhere. But the more obvious problem is that the list of possible items is hard-coded into the report; items which don't fit one of these if statements don't get displayed.
At no point, did the person writing this see the pattern of "I check if a field equals a string, and then set another field equal to that string," and say, "maybe there's a better way?" At no point, in the testing process, did anyone try this report with a new item?
It was easy enough for Eddie to change the name of the column in the results grid, and replace all this code with a simpler: grdResults.Columns.FromKey("POSItem").Header.Caption = POSItemDesc , which also had the benefit of actually working, but we're all left puzzling over why this happened in the first place. It's not like the HPC was getting paid per line of code. Right? Right?
Of course not- no HPC would willingly be paid based on any metric that has an objective standard, even if the metric is dumb.
 [Advertisement]
ProGet’s got you covered with security and access controls on your NuGet feeds. Learn more.
| Friday, June 6th, 2025 | LJ.Rossia.org makes no claim to the content supplied through this journal account. Articles are retrieved via a public feed supplied by the site for this purpose. |
6:30 am |
Error'd: There's No Place Like ... London!
This week, we're showcasing some multiple submissions from two
regular participants who fell into the theme. Everybody else is
just going to have to wait for their turn next week.
Frist up it's
Daniel D.
"I wanted to see events for the dates I would be in London. Is
Skiddle (the website in question) telling me I should come to
London more often?" They're certainly being very generous with their interpretation of dates.
But wait, there's more! Daniel follows with a variation:
"Skiddle here again - let's choose June 7th to June 14th, but Skiddle knows
better and sets the dates to June 6th to June 13th."
"I was not aware the Berlin to London route passes through Hawaii
(which is
Mokulele'shome turf)" chuckles our old friend
Michael R.
He seems to believe it's
an Error'd but I think the real WTF is simply the
Byzantine tapestry of partnerships, resellers, rebranding,
whitelabeling and masquerades in the air transport biz.
"Maybe it's just a Monday morning thing," he reports
from the airport.
But Monday had everybody troubled, and
Michael was already thinking of Friday.
"I am so sure I took the Circle Line just last Friday.
And the other lines have the option Monday-Friday/Saturday/Sunday."
I hope there isn't a subtext here.
 [Advertisement]
Keep the plebs out of prod. Restrict NuGet feed privileges with ProGet. Learn more.
| Thursday, June 5th, 2025 | LJ.Rossia.org makes no claim to the content supplied through this journal account. Articles are retrieved via a public feed supplied by the site for this purpose. |
6:30 am |
CodeSOD: Integral to a Database Read One of the key points of confusion for people unfamiliar with Java is the distinction between true object types, like Integer , and "primitive" types, like int . This is made worse by the collection types, like ArrayList , which needs to hold a true object type, but can't hold a primitive. A generic ArrayList<Integer> is valid, but ArrayList<int> won't compile. Fortunately for everyone, Java automatically "boxes" types- at least since Java 5, way back in 2004- so integerList.add(5) and int n = integerList.get(0) will both work just fine.
Somebody should have told that to Alice's co-worker, who spends a lot of code to do some type gymnastics that they shouldn't have:
try {
ps = conn.prepareStatement(SQL_GET_LOT_WORKUP_STATUSES);
ps.setLong(1, _lotId);
rs = ps.executeQuery();
while (rs.next()) {
result.add(new Integer(rs.getInt(1)));
}
}
finally {
CloseUtil.close(ps,rs);
}
_workupStatuses = new int[result.size()];
for (int h=0; h<result.size(); h++) {
_workupStatuses[h] = ((Integer)result.get(h)).intValue();
}
This runs a query against the database, and then iterates across the result to populate a List type with integers, and right away we're getting into confused territory. rs.getInt returns an int primitive, which they manually box with new Integer , and stuff into the List . And look, I wouldn't really call that a WTF, but it's what they do next that leaves me scratching my head.
They initialize a private member, _workupStatuses to a new array of int s. Then they copy every integer from the result collection into the array, first by casting the get return value to Integer , then by pulling off the intValue .
In the end, this whole dance happens because Java ResultSet types open cursors on the database side and thus don't have the capacity to tell you how many rows they returned. You need to iterate across each record until it runs out of results. That's why they populate an intermediate list. Then they can check the size and create an array, but that itself is a big why. I'm not going to say that using arrays in Java is an instant anti-pattern, but it's always something to be suspicious of, especially when you're holding result sets. It's probably a premature optimization: the key performance distance is on insertions where an ArrayList may need to resize and copy its internal backing store.
My suspicion, however, is that this code falls into the category of "C programmer forced to do Java". They're comfortable with an array of integers, which is covers 90% of the data types you use in C but a dynamic, complicated data structure is horrifying to them. So they use it when they absolutely have to, and then throw it away as quickly as they can to get back to what they're familiar with.
[Advertisement] Plan Your .NET 9 Migration with ConfidenceYour journey to .NET 9 is more than just one decision.Avoid migration migraines with the advice in this free guide. Download Free Guide Now!
| Wednesday, June 4th, 2025 | LJ.Rossia.org makes no claim to the content supplied through this journal account. Articles are retrieved via a public feed supplied by the site for this purpose. |
6:30 am |
CodeSOD: Anything and Everything Today's short function comes from Janusz, and it's anything you want it to be:
public static function isAnything($data)
{
return true;
}
Honestly, I'm surprised that it was made static . Sure, static is the correct choice for this function, at least if we're describing anything about this function as "correct". I'm still surprised. It's got an accurate name given its behavior, it's scoped correctly. It still shouldn't exist and I have no idea what lead to it existing, but that's not surprising.
 [Advertisement]
Keep the plebs out of prod. Restrict NuGet feed privileges with ProGet. Learn more.
| Tuesday, June 3rd, 2025 | LJ.Rossia.org makes no claim to the content supplied through this journal account. Articles are retrieved via a public feed supplied by the site for this purpose. |
6:30 am |
CodeSOD: Continuous Installation A recent code-review on a new build pipeline got Sandra's attention (previously). The normally responsible and reliable developer responsible for the commit included this in their Jenkinsfile:
sh '''
if ! command -v yamllint &> /dev/null; then
if command -v apt-get &> /dev/null; then
apt-get update && apt-get install -y yamllint
elif command -v apk &> /dev/null; then
apk add --no-cache yamllint
elif command -v pip3 &> /dev/null; then
pip3 install --break-system-packages yamllint
fi
fi
find . -name '*.yaml' -exec yamllint {} \\; || true
find . -name '*.yml' -exec yamllint {} \\; || true
'''
So the goal of this script is to check to see if the yamllint command is available. If it isn't, we check if apt-get is available, and if it is, we use that to install yamllint . Failing that, we try apk , Alpine's package manager, and failing that we use pip3 to install it out of PyPI. Then we run it against any YAML files in the repo.
There are a few problems with this approach.
The first, Sandra notes, is that they don't use Alpine Linux, and thus there's no reason to try apk . The second is that this particular repository contains no Python components and thus pip is not available in the CI environment. Third, this CI job runs inside of a Docker image which already has yamllint installed.
Now, you'd think the developer responsible would have known this, given that this very merge request also included the definition of the Dockerfile for this environment. They'd already installed yamllint in the image.
Sandra writes:
This kind of sloppiness is also wildly out of character for him, to the point where my first thought was that it was AI-generated - especially since this was far from the only WTF in the submitted Jenkinsfile. Thankfully, it didn't pass code review and was sent back for intensive rework.
Finally, while the reality is that we'll always need to resolve some dependencies at build time, things like "tooling" and "linters" really belong in the definition of the build environment, not resolved at build time.
 [Advertisement]
ProGet’s got you covered with security and access controls on your NuGet feeds. Learn more.
| Monday, June 2nd, 2025 | LJ.Rossia.org makes no claim to the content supplied through this journal account. Articles are retrieved via a public feed supplied by the site for this purpose. |
6:30 am |
Making a Pass of Yourself Frederico planned to celebrate the new year with friends at the exotic international tourist haven of Molvania. When visiting the area, one could buy and use a MolvaPass (The Most Passive Way About Town!) for free or discounted access to cultural sites, public transit, and more. MolvaPasses were available for 3, 7, or 365 days, and could be bought in advance and activated later.

Still outside the country the week before his trip, Frederico had the convenience of buying a pass either online or via an app. He elected to use the website, sitting down before his home PC and entering the address into his web browser. Despite his fiber internet connection, he sat on a white screen for several seconds while the GoMolva Tourist Board website loaded. He then clicked the obvious Buy Now button in the top-right corner. After several more seconds, he was presented with a page requiring him to create an account.
Frederico did so, specifying his email address and a 16-character password suggested by Bitwarden. He then received a confirmation link in his email inbox. Upon clicking that, he was presented with an interface where he could add MolvaPasses to a shopping cart. He selected one 3-day pass and paid with PayPal. The website redirected him to the proper screen; he entered his PayPal credentials and confirmed the payment.
From there, he was redirected to a completely white screen. After waiting several seconds, a minute ... nothing changed. PayPal sent him a receipt, but there was no confirmation from the GoMolva Tourist Board website.
Frederico decided to refresh the page. This time, he saw the default Apache screen on CentOS.
His jaw almost hit the floor. They were still using CentOS, despite the fact that it'd been abandoned? Horrified, he bailed on that tab, desperately opening a fresh one and manually entering the URL again.
Finally, the page loaded successfully. Frederico was still logged in. From there, he browsed to the My Passes section. His 3-day MolvaPass was there, listed as Not activated.
This was exactly what Frederico had hoped he would see. With a sigh of relief, he turned his attention away from his laptop to his phone. For the sake of convenience, he wanted to download the MolvaPass app onto his phone. Upon doing so, he opened it and entered his username and password on the initial screen. After clicking Login, the following message appeared: The maximum length of the password is 15 characters.
Frederico's blood froze. How was that possible? There'd been no errors or warnings when he'd created his login. Everything had been fine then. Heart pounding, Frederico tried logging in again. The same error appeared. He switched back to his computer, where the site was still open. He browsed to My Account and selected Change Password.
A new screen prompted him for the old password, and a new one twice. He hurriedly filled in the fields and clikced the Change Password button.
A message appeared: Your MolvaPass has been successfully activated.
"What?!" Frederico blurted out loud. There was nothing to click but an OK button.
A follow-up message assured him, Password has been successfully changed.
As terror bolted down his spine, an expletive flew from his mouth. He navigated back to My Passes. There beside his newly-purchased pass was the big green word Activated.
"I only changed the password!" he pleaded out loud to a god who clearly wasn't listening. He forced a deep breath upon his panicked self and deliberated what to do from there. Support. Was there any way to get in touch with someone who could undo the activation or refund his money? With some Googling, Frederico found a toll-free number he could call from abroad. After he rapidly punched the number into his phone, a stilted robot voice guided him through a phone menu to the "Support" option.
We're getting somewhere, Frederico reassured himself.
"FoR MoLvaPaSs suPpOrt, uSe ThE cOnTaCt FoRm oN tHe GoMoLvA WeBzOnE." The robot hung up.
Frederico somehow refrained from hurling his phone across the room. Turning back to his PC, he scrolled down to the website footer, where he found a Contact us link. On this page, there was a contact form and an email address. Frederico filled out the contact form in detail and clicked the Submit button.
A new message appeared: Unable to send the request, try again later.
Frederico rolled his eyes toward the heavens. Somehow, he managed to wait a good five minutes before trying again—in vain. Desperately, he took his detailed message and emailed it to the support address, hoping for a quick response.
Minutes crawled past. Hours. Nothing by the time Frederico went to bed. It wasn't until the next morning that a response came back. The entire message read: The MolvaPass should have been activated once you reached Molvania, not before.
Consumed with soul-burning fury, Frederico hit Caps Lock on his keyboard. MAYBE MY PREVIOUS EMAIL WAS TOO LONG OR DIFFICULT TO UNDERSTAND?? ALL I DID WAS CHANGE THE PASSWORD!!!!
Several hours later, the following reply: The change of pw is not related to the activation of the pass.
Frederico directed his rage toward escalating the matter. He managed to track down the company that'd built the GoMolva website, writing to their support to demand a cancellation of the MolvaPass and a full refund. A few hours later, their reply asked for his PayPal transaction code so they could process the request.
In the end, Frederico got his money back and resolved to wait until he was physically in Molvania before attempting to buy another MolvaPass. We can only hope he rang in the new year with sanity intact.
 [Advertisement]
Keep the plebs out of prod. Restrict NuGet feed privileges with ProGet. Learn more.
| Friday, May 30th, 2025 | LJ.Rossia.org makes no claim to the content supplied through this journal account. Articles are retrieved via a public feed supplied by the site for this purpose. |
6:30 am |
Error'd: Lucky Penny
High-roller
Matthew D.
fears Finance.
"This is from our corporate expense system. Will they flag my expenses in the April-December quarter as too high? And do we really need a search function for a list of 12 items?"
Tightfisted
Adam R.
begrudges a trifling sum.
"The tipping culture is getting out of hand. After I chose 'Custom Tip'
for some takeout, they filled out the default tip with a few extra femtocents. What a rip!"
Cool Customer
Reinier B.
sums this up:
"I got some free B&J icecream a while back. Since one of them was
priced at €0.01, the other one obviously had to cost zero
point minus 1 euros to make a total of zero euro. Makes sense. Or
probably not."
An anonymous browniedad is ready to pack his poptart off for the summer.
"I know {First Name} is really excited for camp..."
Kudos on getting Mom to agree to that name choice!
Finally, another anonymous assembler's retrospective visualisation.
"CoPilot rendering a graphical answer of the semantics of a pointer.
Point taken. "
There's no error'd
here really, but I'm wondering how long before this kind of
wtf illustration lands somewhere "serious".
 [Advertisement]
Keep the plebs out of prod. Restrict NuGet feed privileges with ProGet. Learn more.
| Thursday, May 29th, 2025 | LJ.Rossia.org makes no claim to the content supplied through this journal account. Articles are retrieved via a public feed supplied by the site for this purpose. |
6:30 am |
CodeSOD: Recasting the Team Nina's team has a new developer on the team. They're not a junior developer, though Nina wishes they could replace this developer with a junior. Inexperience is better than whatever this Java code is.
Object[] test = (Object[]) options;
List<SchedulePlatform> schedulePlatformList = (List<SchedulePlatform>)((Object[])options)[0];
List<TableColumn> visibleTableCols = (List<TableColumn>)((Object[])options)[1];
We start by casting options into an array of Object s. That's already a code stench, but we actually don't even use the test variable and instead just redo the cast multiple times.
But worse than that, we cast to an array of object, access an element, and then cast that element to a collection type. I do not know what is in the options variable, but based on how it gets used, I don't like it. What it seems to be is a class (holding different options as fields) rendered as an array (holding different options as elements).
The new developer (ab)uses this pattern everywhere.
 [Advertisement]
ProGet’s got you covered with security and access controls on your NuGet feeds. Learn more.
| Wednesday, May 28th, 2025 | LJ.Rossia.org makes no claim to the content supplied through this journal account. Articles are retrieved via a public feed supplied by the site for this purpose. |
6:30 am |
CodeSOD: Format Identified Many nations have some form of national identification number, especially around taxes. Argentina is no exception.
Their "CUIT" (Clave Única de Identificación Tributaria) and "CUIL" (Código Único de Identificación Laboral) are formatted as "##-########-#".
Now, as datasets often don't store things in their canonical representation, Nick's co-worker was given a task: "given a list of numbers, reformat them to look like CUIT/CUIL. That co-worker went off for five days, and produced this Java function.
public String normalizarCuitCuil(String cuitCuilOrigen){
String valorNormalizado = new String();
if (cuitCuilOrigen == null || "".equals(cuitCuilOrigen) || cuitCuilOrigen.length() < MINIMA_CANTIDAD_ACEPTADA_DE_CARACTERES_PARA_NORMALIZAR){
valorNormalizado = "";
}else{
StringBuilder numerosDelCuitCuil = new StringBuilder(13);
cuitCuilOrigen = cuitCuilOrigen.trim();
Matcher buscadorDePatron = patternNumeros.matcher(cuitCuilOrigen);
while (buscadorDePatron.find()){
numerosDelCuitCuil.append(buscadorDePatron.group());
}
valorNormalizado = numerosDelCuitCuil.toString().substring(0,2)
+ "-"
+ numerosDelCuitCuil.toString().substring(2,numerosDelCuitCuil.toString().length()-1)
+ "-"
+ numerosDelCuitCuil.toString().substring(numerosDelCuitCuil.toString().length()-1, numerosDelCuitCuil.toString().length());
}
return valorNormalizado;
}
We start with a basic sanity check that the string exists and is long enough. If it isn't, we return an empty string, which already annoys me, because an empty result is not a good way to communicate "I failed to parse".
But assuming we have data, we construct a string builder and trim whitespace. And already we have a problem: we already validated that the string was long enough, but if the string contained more trailing whitespace than a newline, we're looking at a problem. Now, maybe we can assume the data is good, but the next line implies that we can't rely on that- they create a regex matcher to identify numeric values, and for each numeric value they find, they append it to our StringBuilder . This implies that the string may contain non-numeric values which need to be rejected, which means our length validation was still wrong.
So either the data is clean and we're overvalidating, or the data is dirty and we're validating in the wrong order.
But all of that's a preamble to a terrible abuse of string builders, where they discard all the advantages of using a StringBuilder by calling toString again and again and again. Now, maybe the function caches results or the compiler can optimize it, but the result is a particularly unreadable blob of slicing code.
Now, this is ugly, but at least it works, assuming the input data is good. It definitely should never pass a code review, but it's not the kind of bad code that leaves one waking up in the middle of the night in a cold sweat.
No, what gets me about this is that it took five days to write. And according to Nick, the responsible developer wasn't just slacking off or going to meetings the whole time, they were at their desk poking at their Java IDE and looking confused for all five days.
And of course, because it took so long to write the feature, management didn't want to waste more time on kicking it back via a code review. So voila: it got forced through and released to production since it passed testing.
 [Advertisement]
Keep all your packages and Docker containers in one place, scan for vulnerabilities, and control who can access different feeds. ProGet installs in minutes and has a powerful free version with a lot of great features that you can upgrade when ready. Learn more.
| Tuesday, May 27th, 2025 | LJ.Rossia.org makes no claim to the content supplied through this journal account. Articles are retrieved via a public feed supplied by the site for this purpose. |
6:30 am |
The Missing Link of Ignorance Our anonymous submitter, whom we'll call Craig, worked for GlobalCon. GlobalCon relied on an offshore team on the other side of the world for adding/removing users from the system, support calls, ticket tracking, and other client services. One day at work, an urgent escalated ticket from Martin, the offshore support team lead, fell into Craig's queue. Seated before his cubicle workstation, Craig opened the ticket right away:

The new GlobalCon support website is not working. Appears to have been taken over by ChatGPT. The entire support team is blocked by this.
Instead of feeling any sense of urgency, Craig snorted out loud from perverse amusement.
"What was that now?" The voice of Nellie, his coworker, wafted over the cubicle wall that separated them.
"Urgent ticket from the offshore team," Craig replied.
"What is it this time?" Nellie couldn't suppress her glee.
"They're dead in the water because the new support page was, quote, taken over by ChatGPT."
Nellie laughed out loud.
"Hey! I know humor is important to surviving this job." A level, more mature voice piped up behind Craig from the cube across from his. It belonged to Dana, his manager. "But it really is urgent if they're all blocked. Do your best to help, escalate to me if you get stuck."
"OK, thanks. I got this," Craig assured her.
He was already 99.999% certain that no part of their web domain had gone down or been conquered by a belligerent AI, or else he would've heard of it by now. To make sure, Craig opened support.globalcon.com in a browser tab: sure enough, it worked. Martin had supplied no further detail, no logs or screenshots or videos, and no steps to reproduce, which was sadly typical of most of these escalations. At a loss, Craig took a screenshot of the webpage, opened the ticket, and posted the following: Everything's fine on this end. If it's still not working for you, let's do a screenshare.
Granted, a screensharing session was less than ideal given the 12-hour time difference. Craig hoped that whatever nefarious shenanigans ChatGPT had allegedly committed were resolved by now.
The next day, Craig received an update. Still not working. The entire team is still blocked. We're too busy to do a screenshare, please resolve ASAP.
Craig checked the website again with both laptop and phone. He had other people visit the website for him, trying different operating systems and web browsers. Every combination worked. Two things mystified him: how was the entire offshore team having this issue, and how were they "too busy" for anything if they were all dead in the water? At a loss, Craig attached an updated screenshot to the ticket and typed out the best CYA response he could muster. The new support website is up and has never experienced any issues. With no further proof or steps to reproduce this, I don't know what to tell you. I think a screensharing session would be the best thing at this point.
The next day, Martin parroted his last message almost word for word, except this time he assented to a screensharing session, suggesting the next morning for himself.
It was deep into the evening when Craig set up his work laptop on his kitchen counter and started a call and session for Martin to join. "OK. Can you show me what you guys are trying to do?"
To his surprise, he watched Martin open up Microsoft Teams first thing. From there, Martin accessed a chat to the entire offshore support team from the CPO of GlobalCon. The message proudly introduced the new support website and outlined the steps for accessing it. One of those steps was to visit support.globalcon.com.
The web address was rendered as blue outlined text, a hyperlink. Craig observed Martin clicking the link. A web browser opened up. Lo and behold, the page that finally appeared was www.chatgpt.com.
Craig blinked with surprise. "Hang on! I'm gonna take over for a second."
Upon taking control of the session, Craig switched back to Teams and accessed the link's details. The link text was correct, but the link destination was ChatGPT. It seemed like a copy/paste error that the CPO had tried to fix, not realizing that they'd needed to do more than simply update the link text.
"This looks like a bad link," Craig said. "It got sent to your entire team. And all of you have been trying to access the support site with this link?"
"Correct," Martin replied.
Craig was glad he couldn't be seen frowning and shaking his head. "Lemme show you what I've been doing. Then you can show everyone else, OK?"
After surrendering control of the session, Craig patiently walked Martin through the steps of opening a web browser, typing support.globalcon.com into the header, and hitting Return. The site opened without any issue. From there, Craig taught Martin how to create a bookmark for it.
"Just click on that from now on, and it'll always take you to the right place," Craig said. "In the future, before you click on any hyperlink, make sure you hover your mouse over it to see where it actually goes. Links can be labeled one thing when they actually take you somewhere else. That's how phishing works."
"Oh," Martin said. "Thanks!"
The call ended on a positive note, but left Craig marveling at the irony of lecturing the tech support lead on Internet 101 in the dead of night.
|
[ << Previous 20 ]
LJ.Rossia.org makes no claim to the content supplied through this journal account. Articles are retrieved via a public feed supplied by the site for this purpose.
|