
I shipped a word processor that formatted the hard drive every 1024 saves - todsacerdoti
https://twitter.com/geepawhill/status/1256342997643526151
======
freedomben
My favorite all time bug was the infamous "Bumblebee" commit of 2011[1]. IIRC
this was the first github commit to go viral. Make sure you have 30 minutes to
read the thread. It is gold.

I have written variants of "GIANT BUG... causing /usr to be deleted... so
sorry...." into commit messages over the years. Such a classic part of
history.

[1] Commit thread: [https://github.com/MrMEEE/bumblebee-Old-and-
abbandoned/commi...](https://github.com/MrMEEE/bumblebee-Old-and-
abbandoned/commit/a047be85247755cdbe0acce6f1dafc8beb84f2ac)

[2] Issue thread (not as good): [https://github.com/MrMEEE/bumblebee-Old-and-
abbandoned/issue...](https://github.com/MrMEEE/bumblebee-Old-and-
abbandoned/issues/123)

EDIT: Github is timing out trying to load it. May want to use archive.org:
[https://web.archive.org/web/20130613012555/https://github.co...](https://web.archive.org/web/20130613012555/https://github.com/MrMEEE/bumblebee-
Old-and-abbandoned/commit/a047be85247755cdbe0acce6f1dafc8beb84f2ac)

~~~
contravariant
That's the most hilarious diff I've ever seen.

At least it's hilarious now, for some people it must've been horrifying.

~~~
onemoresoop
This is why in general I am not the first to get an update, unless I've been
waiting for a fix for a while. I also think how shitty the person must have
felt for the screw-up. We all screwed up at some point too, I remember
removing a database by accident (it was a Dev, luckily not Prod and i was a
junior 20 years ago. ), but having that stick like it does nowadays is not
pleasant thought. I learned my lesson, and as a rule of thumb I always comb
the code a couple of times before I commit.

~~~
AceJohnny2
Also why web-powered rolling/staggered updates are a thing

------
cperciva
This reminds me of a bug I ran into in some beta software on Windows many
years ago:

1\. Create the directory "C:\APPNAME-tmp"

2\. Change the current directory to "C:\APPNAME-tmp"

3\. Recursively delete everything under the current directory.

This worked fine for thousands of users until I came along -- running Windows
2000, with the "C:\" directory read-only for unprivileged users, running as an
unprivileged user. At that point it became:

1\. Try, and fail, to create the directory "C:\APPNAME-tmp"

2\. Try, and fail, to change the current directory to "C:\APPNAME-tmp"

3\. Recursively delete everything under the current directory, which is my
home directory.

The authors were very apologetic when I pointed out the bug.

~~~
maxyme
The Steam Linux client had a very similar issue a few years ago where in
certain configurations it would delete /
[https://github.com/ValveSoftware/steam-for-
linux/issues/3671](https://github.com/ValveSoftware/steam-for-
linux/issues/3671)

------
renewiltord
These are great. Steam Linux's universal rm is too.

[https://github.com/valvesoftware/steam-for-
linux/issues/3671](https://github.com/valvesoftware/steam-for-
linux/issues/3671)

Featuring probably the most unflappable human in the history of time as a bug
reporter. One day I hope to have the fortitude this man does.

~~~
PureParadigm
You can have his fortitude in the face of all your files being deleted if you
have a robust, automated backup policy.

One of my professors used to say that he should be able to destroy your
laptop, buy you an equivalent new one, and you should be up and running again
within a few hours. Hard drives fail all the time and computers get
lost/damaged/stolen. Losing your home directory on a computer should be
expected, and definitely not the end of the world.

~~~
ip26
I prefer the raid5 approach, I leave my junk strewn all over a sufficiently
large number of computers- odds are I'll still have a recent copy somewhere if
my laptop explodes.

~~~
canada_dry
> I prefer the raid5 approach

I've been using _actual_ raid5 (via adaptec raid card) for years and very
recently had one of my trusty 5TB HGST drives fail (after 3+ yrs of uptime).

Fortunately the rebuild worked, but there are so many horror stories of raid5
rebuilds NOT working it has me contemplating going back to simple mirroring.

~~~
cyphar
Mirrors are generally better because you get shorter resilver times and you
don't stress all the disks in your pool when you resilver (which is why a lot
of disk failures happen during RAID5 rebuilds -- the rest of the pool's disks
are old). The downside is that it uses more disks for the same level of
redundancy.

I would also mention it's probably a good idea to use something like ZFS
rather than a hardware RAID card. In general, free software RAID is better
audited and you don't need specific hardware for the recovery process. But
also, ZFS has proper checksumming, so you won't have to worry about all sorts
of silent corruption (which RAID blissfully ignores -- most implementations
will just recompute the parity in case of a mismatch, which is the wrong thing
to do (1-1/n) of the time).

~~~
canada_dry
> a good idea to use something like ZFS

Was hoping to utilize ZFS in 20.04... but the whole SNAP issue has me sticking
with my current version.

Perhaps it's time to find a _dummies_ guide to setting up ZFS on 18.04 LTS.

~~~
lmm
Have you considered FreeBSD? ZFS support by default, and none of the junk that
recent Linux distributions have been moving towards.

------
pmiller2
This is an amusing story, but I disagree with not using numeric literals. Most
of the time, sure, you don't want to use numeric literals, but, sometimes, you
do. I posted my example in another comment here.

As for the other conclusion, I have a story of my own. I once shut down all of
my company's asynchronous task processing for about 20 minutes, completely by
mistake. Our web servers kept serving, and nobody external would have noticed
a difference, but, for 20 minutes, our scrapers stopped scraping, our NLP
classifiers stopped classifying, and a bunch of stuff that made us money
wasn't happening. Had I not noticed it and fixed it ASAP, we probably would
have lost money. Instead, I immediately announced what I had done, got help,
and we fixed it.

The real moral of the story is that an honest mistake is nothing to be ashamed
of. I make mistakes all the time. Some of them make it into production. Big
deal. Everybody does.

------
rincebrain
There used to be an absolutely fascinating bug with Wine and Diablo II - if
you had raw write access to /dev/hda, running Diablo II would nuke your MBR,
so on next reboot, you'd be staring at No Operating System Found. [1] is a
Gentoo forum post about it, I can't find the Wine bug.

This didn't happen on Windows, just in Wine. It also went away in the 1.10
patch IIRC, so whatever mysterious behavior resulted in that got fixed.

edit: Found it! [2] It was even more recent than I remembered.

[1] -
[https://forums.gentoo.org/viewtopic-p-2723361.html?sid=3c70a...](https://forums.gentoo.org/viewtopic-p-2723361.html?sid=3c70ad39fad18fe01a49bbc8c61e0356)

[2] -
[https://bugs.winehq.org/show_bug.cgi?id=4672](https://bugs.winehq.org/show_bug.cgi?id=4672)

~~~
rvnx
The outcome of the WineHQ bug isn't clear, was it eventually fixed ?

~~~
rincebrain
My recollection (which has already proven faulty) was that the problem
eventually went away with a later patch; it could also be that as most distros
don't put users in a "disk" group any more by default, that it's simply gone
away as a side effect.

------
dredmorbius
[https://threadreaderapp.com/thread/1256342997643526151.html](https://threadreaderapp.com/thread/1256342997643526151.html)

~~~
freedomben
The parent comment link takes you to the full story in a blog post of the OP.

~~~
dredmorbius
"Threadreader' is a service which aggregates a thread of Twitter posts, by a
single author (no replies), without the annoyances and repetitive elements of
individual tweets. It also integrates all images into the thread, something
Twitter itself often fails to do. The textual content is the payload of the
original Twitter thread, other than as noted. Whilst often having the
appearance of a blog post, it is in fact the original content, only presented
vastly more sanely.

------
chx
We were a young startup we went to a conference... when the site went down and
we found someone DoSing us. But... there was little network traffic however
the database was loaded beyond any reason. Turns out, the image importer from
mail had a bug in error handling and a broken email came in so it just kept
retrying creating an image entity in the database. Ten thousand broken images
before we stopped the party, in 2005, that was enough to crash our little
server. We DoS'd ourselves.

------
randomsearch
Worked with someone who implemented an archival program. Instead of deleting
the archived records, it deleted those that weren’t archived.

The records were orders. Millions of orders.

~~~
jpxw
The thought of realising that mistake makes me feel sick to the stomach

~~~
randomsearch
(Trying to keep it anonymous) A large international IT company kept backups
for the company off-site. Consultants from the company were called in, and the
orders were eventually restored - I think it took days, but they got there.
Orders were delayed and it cost the company a lot of money. No-one was fired.

------
thomasahle
An early version of PyChess had an uninstall script thst would remove the
user's entire homedirectory.

~~~
minikites
Bungie did that with Myth 2:
[https://youtu.be/-p3a8eGORKY?t=513](https://youtu.be/-p3a8eGORKY?t=513)

~~~
gpderetta
Valve did it recently with Steam on linux!

~~~
jtlienwis
There was once was an operating systems that allowed you to format your entire
hard drive when you only intended to format a floppy disk, if you typed format
c: instead of format a:. This was called Microsoft Dos 2.x.

~~~
Symbiote

      mkfs.vfat /dev/sda1
    

That's not that much different from a plausible error on Linux, with a USB
drive and a hard drive.

(At least, the man page for my mkfs.vfat doesn't include any options
suggesting it protects against formatting already-formatted or mounted
filesystems.)

~~~
Dylan16807
Yikes, it sure doesn't. For comparison, mkfs.ext2 asks before proceeding if
there's already a filesystem, and outright exits if it's mounted.

~~~
Symbiote
Fair enough -- I was assuming based on the lack of documented "force" options
that other mkfs' (mkfs.ext4 etc) have.

------
StreamBright
I still like the one when ubuntu devs decided that netcat's behavior to keep
the connection open and wait for the answer when connecting to a port is
outrageous and closed the connection after sending the request. We used netcat
to debug network connectivity. The day I learned that I cannot trust any piece
of software that is part of ubuntu. Later the also pretty good purify
complains bug followed. Those guys might have been the Debian folks.

~~~
meddlepal
I cannot for the life of me figure out how Ubuntu became so popular, it's kind
of a hot mess.

~~~
rvnx
Because Ubuntu included proprietary drivers by default, notably ATi and NVIDIA
and Wi-Fi cards, all of them were so tedious to install on Debian (which was
one of the most popular Linux distributions at the time)

~~~
necovek
It also shipped latest free software from two months ago (GNOME, X) that
actually worked on a 6 months schedule! (Remember Debian releases back in the
day? If you attempted to get your USB flash drives to just work, you'd
otherwise be recompiling half of your system and Gnome with Garnome or
jhbuild)

And it shipped actual, physical CDs across the world for free. It was 2004!

Then it shipped a free LTS that may not have been as stable as RHEL, but it
was definitely fresher and with guaranteed updates (for main) for 5 years (3
on desktops early on). It was 2006.

------
quezzle
Or put more positively:

“I shipped a hard disk formatting utility that doubled as a word processor.”

------
HenryBemis
Oh I laughed so hard!! Computing has come a loooooong way since the early 80s.
Oh what a gift is for humanity, what a great tool (not the specific word
processor but hey, we've all made mistakes).

~~~
splintercell
We once shipped a product (2011) which would delete user's account (and all
his data) from the website when all they wanted to do is to 'unfollow'
someone. It was hilarious issue of MySQL database issue, instead of deleting
the record of the 'follow' it basically removed user's record and thus
removing all their files and entries.

------
ineedasername
Recursive email: Very early in my career, I made something accidentally
recursive.

There's a reporting & data extraction language called Focus (nowadays
WebFocus). I was working in a very old version, and had a few nested GOTO
statements to form a loop where the final output was a customized email sent
for each row of a query returned. I had to make a simple update, but
accidentally deleted a line first. I reinserted it... one line off from where
it had been. My careful GOTO structure went from a loop, to recursive. Instead
of sending an email to each row returned, I sent an email to the first person.
Then I sent an email to the second person _and_ the first. Then to the third,
_and_ the second, _and_ the first.

The list was about 1,000 recipients... but luckily it usually finished very
quick, and I would monitor as it went, and noticed the long run time after
about 100 iterations and killed it. I then checked the logs to see why it ran
so long, and traced back my error and fixed it... and sent an apology email to
the 100 recipients I accidentally spammed.

------
raverbashing
This one is good as well (on the original thread):
[https://twitter.com/kevin/status/1256431142086955009](https://twitter.com/kevin/status/1256431142086955009)

Pro-tip: turn-on the alerts _after_ deploying the site.

------
userbinator
Microsoft has had its share of giant fuckups too, although from memory they
seem to be more recent:
[https://news.ycombinator.com/item?id=18189139](https://news.ycombinator.com/item?id=18189139)

I've been writing code for about as long as him, but because I started with
Asm, which makes one become _really_ careful with buffer sizes, doing
something like making one thing larger would not be done without carefully
looking "down the line" to see if any further changes were required; and they
almost certainly were. That's not to say I haven't corrupted files before, but
fortunately nothing quite as catastrophic as wiping the disk.

------
benibela
Recently I got a phone call during breakfast that texstudio had scrambled the
file when saving, by rearranging blocks of it randomly. The user had triple
backups, on the hdd, usb stick and another one (dropbox?). All files were
useless after he saved them at the same time :/

Might be some memory corruption caused by a wrong pointer in any other part
besides the saving?

------
dekhn
I never documented the "quit" command for a MUD client I wrote on VMS back in
'89\. For years I got emails from users who couldn't figure out how to exit
the app.

------
atum47
well, I was testing something on s a clone version of a game and end up
publishing that version to the app store. When I uploaded the game on my
phone, my progress ware gone, all my saves. the colone version created a new
database (thank God without deleting the old one). my game only had like 1k
installations, and I found out my mess quick enough. just published a new
update with the original database name and was lost.

------
sfgweilr4f
Ah yes. Back in the days when you chose "New Document" it apparently meant "a
fresh new start". (Or not, I'm glad it was just a bug!)

------
fouc
I thought this was going to be a story about making a simple application with
a deliberate limitation. Like a feature.

------
mod
I :s (save) so compulsively, I think I would reformat my drive about every
day.

------
crimsonalucard
How does an incompetent engineer tell the difference between incompetence and
imposter syndrome?

I don't think it's realistic to say that all incompetent engineers think
they're competent.

------
Konohamaru
This is a "usenet shock site" level screamer.

------
mhh__
Fallout 76 (amongst literally hundreds of recorded bugs) shipped with a bug
that was able to brick PCs and consoles alike.

~~~
rowanG077
Brick PCs?? How?

~~~
meddlepal
They're using the "modern" version of "bricked" which basically means it had
to be reinstalled it factory defaults reset.

~~~
rowanG077
Hmm I never knew this was redefined. Bricked always quite literally means you
device becomes permanently non-functional. I.E. a brick. What is the new word
for this state?

~~~
mhh__
Given that it's almost impossible to do this with modern hardware I don't see
what the distinction is?

I'm not aware of any way to make a modern x86 processor self-destruct.
Apparently you can make an FPGA fry itself but even then not with good heat
conduction away from it.

~~~
rowanG077
Not with a general purpose PC no. But I don't doubt that it is possible to
brick any of the current gen consoles if you try hard enough. Actually many
general purpose laptops probably also can be bricked since the amount of non-
standard hardware is increasing every year.

------
jancsika
I'm going to assume that once users were told the formatting was due to a
really clever C compiler optimization they were probably fine with it.

~~~
FpUser
The software was written in Forth language and at a time when there was no
memory protection.

~~~
dhosek
Youngsters have no concept of 80s computing where so much was accessible to
simple programs.

~~~
RaceWon
> Youngsters have no concept of 80s

In '87 my first 256 computer had 640k of memory with a hd that was less than
1mb IIRC. It cost nearly 5 thousand dollars including the $700 dot matrix
printer.

Let the good times roll!

~~~
greenyoda
The IBM PC/XT, the first IBM PC to be delivered with a hard drive, already had
a 10mb hard drive in 1983, so 1mb sounds too small for your hard drive. 1mb
was roughly the capacity of a floppy disk.

~~~
dhosek
My first PC (in 1991), a no-name luggable with a monochrome plasma display had
a 200MB HD. I remember one of my former professors telling me it was nuts to
get such a large hard drive, that I'd never fill it up. When I bought its
replacement in 1994, the new computer had a 1G hard drive which I split into
200MB partitions with one partition dedicated to a copy of the old computer's
hard drive.

------
klyrs
> Don't use numeric literals for anything but 0, 1, and -1.

Excuse me?! So if I'm writing a prng, should I write the numerical constants
like

    
    
      int modulus = 1 + (1+1+1)*(0 + (1+1+1)*(-1+... )...);

~~~
ztjio
I'm going to assume you're not deliberately trying to misunderstand him for
the sake of a hot take, because, that would be pretty lame. So instead I'll
explain for you and anyone else who doesn't understand him what he meant.

What he is suggesting is that you generally not include literals in your code,
and instead, use a constant/variable that can be traced back to a single place
in order to make changes more visible and easier to deal with. That he makes
exceptions for 1, 0, and -1 is explained by conventions in various languages
where those values in context end up as generic and meaningful as any other
language keyword and thus would not benefit from being referenced from a
constant. That doesn't mean you wouldn't ever end up with constants that are
0, 1 or -1 though, just that you wouldn't assume every random place you might
use those values (such as sorting algorithms) justifies a constant
placeholder.

For further review on the topic, may as well start here:
[https://en.wikipedia.org/wiki/Magic_number_%28programming%29](https://en.wikipedia.org/wiki/Magic_number_%28programming%29)

~~~
klyrs
> I'm going to assume you're not deliberately trying to misunderstand him for
> the sake of a hot take, because, that would be pretty lame.

I'll admit, my example was overwrought with comedic intent, but I stand firm
on this issue. Use a magic number twice? Yeah, go ahead and put that numeric
literal somewhere convenient (but you _still have a numeric literal_ ) to the
consumers of it and easy to find by your readers (not a top-level
magic_numbers.h)

I'm a mathematician. The fear of numbers in code is an affront to the domain
that I work in. YMMV. I put a lot of work into documenting my code, but for
the love of pete, 2 is not a magic number: my example was no more overwrought
than OP's rule.

~~~
mattkrause
It depends on why you're using the 2.

In some cases, I'd say that 1 can be a magic number. For example, it would
better to write

    
    
        fprintf(STDOUT, output_string)

than

    
    
        fprintf(1, output_string)
    

However, 0 and ±1 have a special role in picking out the first/next/previous
elements of a sequence (and related things), which is so common that it'd be
silly to insist on defining POSSIBLE_NEXT_INDEX and POSSIBLE_PREDECESSOR. That
said, people do seem to love Python's itertools, so....maybe that's where
we're headed. I had somebody _aggressively_ complain about the readability of
the all-pairs for-loop, which I thought was basically standard.

    
    
        for(auto i=0; i<N-1; i++)
           for(auto j=i+1; j<N; j++)
             process(X[i], X[j])
    

The flip side is that I don't think you _always_ need to do this. For example,
this is silly:

    
    
       double triangle::area() const { 
          const double NORMALIZATION = 1/2.0;
          return this->base * this->height * NORMALIZATION;
       }
    

The point is just to make it clear why that particular number is being used
and where it came from.

~~~
rmtech
The all pairs loop is unnecessarily low level, and it would be hard to spot a
mistake there. It would be great if there was a way to say

    
    
        for i < j <= N
    

as this is super clear.

~~~
mattkrause
I guess so. I don't think it's _atrocious_ : it looks like iterating over the
upper/lower triangular part of a matrix to me, which is fairly common (in some
domains, I guess). Plus, I like that the double for-loop indicates slowness.

However, Python has itertools.combinations(X,2) and Julia has
IterTools.subsets(X,2) if that's what you want.

~~~
klyrs
I think you mean

    
    
      # see __magic_numbers.py
      itertools.combinations(X, number_of_things_in_a_pair)

~~~
mattkrause
Ha! You’re clearly taking the mickey but...

Some things only/obviously make sense over pairs of items. For those, go with
a literal 2 for x,y in itertools.combinations(obj, 2): if is_overlapping(x,y):
raise OverlapError(x,y)

However, sometimes the subset’s size _just happens_ to be two (but you might
change it), maybe a constant would be good. Ditto if you’re doing some math
where there are “real” 2s that are part of a formula and incidental ones that
are due to the subset size. For example:

    
    
        subset_size = 2
        for subset in itertools.combinations(X, subset_size):
            mse.append(sum((subset - target)**2)/subset_size)
    

is a bit more flexible and more clear than using all 2s, IMO, and at very
little cost (YAGNI blah blah, but I think that’s an argument for not making a
whole configuration system that lets you set the size at runtime).

~~~
klyrs
> Ha! You’re clearly taking the mickey but...

Only in my choice of variable name. OP drew a line at 0, 1 and -1. What I did
there was highlight that the implications of that rule are absurd. See how
your sum of squares also contains a 2? VERBOTEN!!!! And don't you dare re-use
"subset_size" ;)

This is somewhat akin to Dijkstra's opinion on goto. Which is actually _great
advice_ when you're doing apps in javascript, but doesn't get you very far if
you're writing or generating assembly. When such advice is promoted to a
taboo, I side with Churchill: this is the type of arrant pedantry up with
which I will not put. Or Emerson: foolish consistency is the hobgoblin of
little minds.

Yes, too many numeric literals can make code hard to read. But _math is hard
to read_ [1] because you need to _really think about it_ \-- you can't avoid
the complexity; you can only rearrange it. Where you put it is a matter of
taste, and absolutes have absurd consequences.

As for the original notion of indexing a triangular array, I have a greater
concern:

    
    
      for i in range(n):
        for j in range(i):
          foo(array[i][j])
    

this is self-documenting in the sense that I immediately know the relationship
between i and j -- without reading documentation, I can't recall if
itertools.combinations will give me the upper or lower triangle. In this case,
I'd avoid the 2 for entirely different reasons :)

[1] and I don't mean "let's go shopping!" \-- I mean that reading a math
paper, even for experts, can take days per page.

