Every few months, product teams at Figma plan what we call Quality Week, a time to deal with all kinds of bugs—from classic coding errors to strange not-really-bugs, tricky oddities, and things that feel like bugs but technically aren’t. Yesterday, we released the latest fixes to Figma and FigJam that came out of our most recent Quality Week. Here, Design Manager Marcin Wichary shares stories about these seemingly-small improvements, reflects on bugs more broadly, and explains the art of distinguishing little details that you can ignore from the little-big ones that make all the difference.
It was an evening of the fourth day of the last Quality Week, and Molly had a problem. The fix for the bug she’d been working on for the entire day proved to be elusive. On the surface, it seemed like it should be a simple bug to fix: people who used the accent menu in macOS saw their letters repeated or not working at all.
Molly knew a few people tried before her and failed. But she started from where others finished, and eventually figured out it wasn’t a simple issue of business logic gone awry. It turned out to be a glitch in the quiet, invisible choreography of moments that happen whenever you press a key—events like the key is now down, the key has been held for a while, the key is back up, we now know the character that’s about to be printed, the character is now on the screen, and a few more.
Both the operating system and the underlying browser deal with those even before Figma can and in this case, the browsers weren’t doing all the things we expected. But code could be written to help them, and Molly figured out how to write it. On her computer, Figma started correctly handling the accent menu, showing one and only one letter. The fix supported both keyboard and mouse inputs. It was less than ten lines of clean, well-documented code.
But there was a catch the size of an old design system. The new patch worked perfectly in Firefox and Safari, but the problem still persisted in Chrome, the browser with the biggest user base.
“I’ve spent all day on this and I’m so frustrated,” she wrote to a coworker. She did everything she was supposed to. She came up with a fix. She wrote it up and sent for an internal approval. She even filed a report with Chrome’s developers so they could take a look some time in the future. But it felt like a victory on paper only. The bug was fixed, but to most of Figma’s users, the bug wouldn’t be fixed at all.
Where there’s software, there are bugs. Where there’s time, there are more.
In theory, bugs—like all of software engineering—are meant to be precise. A found bug is two pieces of information: how this is supposed to work and how it currently isn’t. Fixing a bug is making something work well again.
How this is supposed to work can seem pretty easy. The most famous bug, Y2K, was simply “computers will think the year 2000 is the year 1900.” The second-famous, the Pentium FDIV bug, was “these two numbers divided gives an incorrect result.”
But where people and machines intersect, things get tricky, and “bugs” take on a wider, less precise meaning. In practice, it often feels there is no difference between something that works as intended, but badly—and something that doesn’t work at all. (One of the most infamous bugs often listed in top ten examples, the too tight trajectory that doomed the Mars Climate Orbiter in 1998, was not a mistake in code: it was two teams inputting values using two different sets of units.) In practice, when dealing with a complex system, how this is supposed to work might not be obvious. In practice, how this is supposed to work can sometimes be a pipe dream, attainable only with infinite time and resources. In practice, you might not be able to get to where you were before—just chart a new, less buggy direction.
Some bugs cannot be fixed, some don’t deserve to be fixed, and others are not bugs at all. Y2K, FDIV, and many others showed us that knowing both what’s broken and even how to fix it is hardly enough. And for a bug the caliber of Y2K that happens once a millennium, there are two thousand smaller ones that happen every year.
At Figma, there are many processes and tools to deal with bugs, including recurring Quality Weeks: time dedicated to coming together within a product team, and to fixing bugs that might otherwise get forgotten by time, bugs that deserve extra investigation, and bugs that stretch the traditional definition of bugs.
One example: support for HEIC files, a relatively new image format popularized by iPhones and iPads. To the rigid definition, Figma not supporting HEIC was never a bug. The code to support it was never written, so nothing stopped working; it never worked to begin with.
To Figma users, however, that distinction was meaningless. Some images dragged from their phones worked, some didn’t. The correct definition of a bug didn’t matter if Figma felt buggy.
Quality Weeks make room for bugs like these. This particular one was fixed by Sawyer, an engineer on the FigJam team: 98 lines of clean code, a relatively painless approval from another engineer. But when you fix a bug, you must be careful not to introduce another one.
Turns out, by their nature, HEIC images in their 15-megapixel glory are usually big and heavy, taking a long time to process. Even after adding proper support for the file format, without any extra work, dragging an HEIC file onto Figma canvas would result in… nothing. For many seconds, as each and every pixel of the image traveled across the globe and then within the innards of the servers, it would seem that Figma ignored the image drop. Only after a while, the image would suddenly appear.
A feature not seeming like it’s working feels the same as the feature not working. Jackie—the designer on our editor platform team, responsible for pursuing and coding the delightful Figma loading animations—flagged this first. The addition of a loading state could help, and it didn’t have to be complicated at all.
But even within that simple fix hid a strange bug, rooted in psychology. Adding a loading state too soon can make things feel slower. So, one extra addition had to happen to make the UI less eager. The loading state itself had to be equipped with its own, invisible loading state—the loading message wouldn’t appear until at least second has passed, so for small images or very fast computers, the important illusion of things happening in real time would be preserved.
It can feel overwhelming at times, those strange fractal allegiances, bugs inside bugs inside bugs, fix quicksands that can swallow you whole.
It gets even trickier if the answer to fixing a bug is to introduce… something that feels very much like one. During this Quality Week, that strange honor fell to Lauren, an engineer on the core editor team specializing in canvas behaviors and rendering (responsible, among many things, for spread shadow and knockout shadow).
The problem: if you put your mouse over an object in Figma, the object welcomes your attention with a hover state. It’s a pretty standard convention that helps target things that might not have the most obvious shapes.
But that convention backfires when you’re working on complex selections, which are often central to how stuff gets done. At Figma, we’re serious about these. Beyond putting selections on the undo stack, we have many features to fine-tune them—from the icons next to Selection Colors, to a variety of Select All With options.
The common way to build a complex, precise selection is Shift+clicking. But if you Shift+click on an object to de-select it, the object will immediately show a hover state that… looks almost exactly like the selected state. That can be confusing. Did I just click this object or not? Is it part of the selection or outside of it?
The obvious fix to this issue—redesigning the hover and selection states to look more distinct—would replace one problem with another, that of visual sprawl. And so, Lauren worked on a different kind of a fix, one debated hotly by designers and engineers just the week before.
The idea was simple: if you Shift+click to deselect an item in a complex selection, Figma will break the hover state until you mouse over the object again.
Introducing an exception always feels uneasy. The solution worked really well in testing, but Lauren just coded something that—to someone who isn’t aware of the nuance—will look like a bug in the future. The hard work here wasn’t just fixing a selection detail. It was also documenting and contextualizing it so that no one, in the future, accidentally fixes the fix.
If those aren’t enough reasons to hate bugs, there are many more. Bugs are, by definition, a look backward—at past behavior, at code that already exists, at the old work of engineers whom you’ve never met. It can feel more fun to write new code, chart new territories, add new functionality.
But the past can be fun, too. A good bug is a puzzle. A mystery. A whodunit. To solve a bug, sometimes you have to be a scientist: observe and measure, chart out the logic, follow the math. But then, two minutes later, you need to wear a hat of a very particular detective—take your flip notepad and interview different pieces of code to understand not what they claim they do, but what they actually do.
The pieces of code are inanimate, and the interviewing is of a strange nature—
console.log(), breakpoints. Shirley—a software engineer on the editor experience team—didn’t know it yet, but she was about to embark on an investigation.
“It confuses me how Figma only supports TrueType fonts, but not OpenType ones,” wrote one Figma user just days before the Quality Week. This was strange. For as long as it’s been around, Figma supported both TTF and OTF fonts—the two most popular type formats—in addition to a few lesser known.
Bug fixing relies on having a solid “repro,” a set of unambiguous steps on how to encounter the bug. The steps exists so that the engineer can see the issue on their computer—and, after coming up with a fix, and seeing repro steps stop causing trouble, have certainty that it actually worked.
Here, the steps were simple enough: “I have an OpenType font. I install it. It works elsewhere. It doesn’t in Figma.” But when Shirley took the font and installed it on her computer, everything worked well. This required a tricky investigation: What was different between those two computers? It ended up being a collaboration between Shirley, support, and a few users who dedicated their time to helping us.
It took many hours, starting with looking at font files. Then, it was screenshots. Later, logs. Without a working repro, instead of seconds, each turn took minutes, if not hours.
The culprit was something no one expected, spotted in a corner of a screenshot taken for an unrelated reason. Nobody thought OTF could stand for anything other than “an OpenType font.” But if you install Open Office, OTF can also mean “Open document formulate template.” On computers with both Figma and OpenOffice installed, some of the font files were identified as document templates, and Figma didn’t know what to do with them. It was an example of a bug falling in between things—a tricky situation even if you control all the things, let alone if you don’t. For Figma, a complex web tool, those situations weren’t uncommon.
It was also an uneasy example of a bug that had to be fixed without reproducing it. It felt like solving a crime without actually seeing a crime scene: how can you make sure things are good if you don’t see them working correctly in front of your eyes? The hypothetical fix had to be deployed and tested outside, adding to the complexity.
But the investigation felt worthwhile. We knew that a bug like this left in the wild can lead to serious consequences. OTF fonts not working could start seeming to people like a deliberate design decision—and just like touching a hot stove for the first time, seeing something not work often makes us assume this will never work again.
Luckily, the fix worked on the first try, saving Shirley from working in the dark over and over again. On the code level, at just seven lines, the patch was trivial. But in a way, that made it worse. In the real world, moving a pebble is easier than moving a mountain. When you deal with software, you can spend a month moving a pebble.
Many of those pebbles won’t matter, bugs with little consequence or ones exotic enough that no one will ever encounter them. But not all pebbles should be ignored. Little little details and little big details look and feel the same. The first group doesn’t deserve attention, but unattended, the second one grows and grows—and the collective presence of hundreds of small bugs in important places might end up being what distinguishes software you want to use and software you merely have to.
Knowing which bugs to treat seriously and which ones to ignore can sometimes be a bigger challenge than actual fixes. There is no formula: just constantly rewriting frameworks, listening to individual users and big companies, picking the brains of designer advocates and support teams, trusting the collective guts of designers, project managers, and engineers who have deeply thought of bugs before, and teaming up to work on things together.
When Delong from the editor team was fixing a bug that slowed down typing by up to an astonishing 1000% percent under some circumstances, it all came with the understanding that an awful lot of typing happens every day, and that there might be nothing worse than a feeling of keys disconnecting from your fingers because of slowness.
When Silas, a FigJam engineer, improved linking—now more objects will have unique URLs—it was out of belief in the power of links and sharing, and how making it even marginally easier to share can lead to better, smoother collaboration.
When Jenning and Chang from the design systems team enabled individual publishing of components directly from the right click menu, it came from an understanding that design systems are incredibly complex, and Figma needs to support different modes of working. Sometimes you don’t want to create a branch, or even go through the regular publishing flow. Sometimes you just need to get one component out there.
And when Alex from the FigJam team added support for creating stamps by drag and drop—not just by clicking—it was out of our shared knowledge and belief that there is sometimes no greater feeling than mastering a complex tool, and it’s our responsibility to build out those paths to mastery.
All those, and hundreds of other bugs, were fixed that very Quality Week in November 2021. Strings were renamed, comments refined, bad code excised, tests added, race conditions solved. It’s entirely possible that in the course of one single day, you might encounter ghosts of dozens of them—successfully dragging an HEIC file into Figma, using it as part of a complex selection, and then publishing the component to the library.
It’s hard to be excited about bugs. Most of them aren’t fun. Most of them don’t come up with cute anecdotes, historical stories, or life-changing learnings. Most of them just… are. You get to fix many, but never all of them, and the failures of bugs you couldn’t fix bother you more than the successes. Sometimes, on a dark day, you cannot escape a feeling: software really wants to be bugs.
What helps is knowing and reminding yourself that fixing bugs is not a theoretical exercise in cleaner coding. Fixing bugs always needs to come back to people using Figma. Sawyer’s HEIC loading state details, Lauren’s deliberate inconsistency, Shirley’s blind investigation all came back to helping Figma users work better and feel more awesome.
And that brings us back to Molly, and her dissatisfaction with her accented menu fix not working in Chrome. Leaving the accent menu broken in Chrome didn’t just mean leaving behind a hypothetical number of theoretical users. It meant ignoring months of reports of people feeling annoyed, frustrated, even disrespected: