Unix's creator named his biggest regret as a single missing letter
When Unix co-creator Ken Thompson was asked what he would change if he could design the operating system again, his answer was legendary: "I'd spell creat with an e." In early Unix, the system call that creates files was named creat() rather than create(). On the memory-starved PDP-11, saving a single character preserved precious bytes in compiler symbol tables. Because software depends on backward compatibility, that missing letter became permanently locked into global POSIX standards.
The Most Famous Typo in Systems Programming
In the history of software engineering, few quips are cited as often as Ken Thompson's reflection on the Unix operating system. Thompson, who co-created Unix at Bell Labs alongside Dennis Ritchie and other researchers, was once asked what he would do differently if he had the opportunity to redesign the system from scratch. His answer bypassed grand architectural questions, security models, and memory management. Instead, he gave a six-word reply: "I'd spell creat with an e."
The joke resonated across the computing community because every systems programmer recognized the reference immediately. At the foundation of the Unix file system sits a system call named creat(). For decades, anyone writing low-level software to generate a file on a Unix or Unix-like operating system has had to write that specific identifier, deliberately omitting the fifth letter of the English word "create." What began as a minor concession to the constraints of primitive hardware evolved into an indelible fixture of modern computing.
Hardware Scarcity and the Six-Character World
To understand why creat() lost its vowel, one has to examine the computing environment of the late 1960s and early 1970s. The earliest versions of Unix were developed on minicomputers such as the Digital Equipment Corporation PDP-7 and later the PDP-11. These machines possessed only a tiny fraction of the memory available on a modern digital wristwatch. Every byte of primary storage was fiercely contested territory, shared between the operating system kernel, user programs, and developer tooling.
In early language implementations, assemblers, and linkers, symbol tables stored the names of variables, functions, and system routines. Memory limits dictated severe caps on identifier lengths. On many systems of that era, external symbols were truncated or limited to six characters so they could fit into compact memory records, such as 32-bit or 36-bit words encoded with condensed character representations. Dropping the final letter allowed "creat" to fit squarely within a six-character ceiling.
Beyond strict technical limits, early Unix design culture favored radical brevity. Commands like cp, mv, rm, ls, and grep eliminated extra characters to save memory and reduce typing over slow mechanical teletype terminals. In this lean, stripped-down environment, shaving a single letter from a routine that created files seemed both natural and practical.
What the creat Function Actually Does
In modern systems, creat() is formally defined by POSIX standards maintained by organizations like The Open Group. The function takes two parameters: a pathname pointing to the destination in the file system and a permission mode specifying access controls for the new file. If the system call succeeds, it returns a non-negative integer representing an open file descriptor—specifically, the lowest-numbered file descriptor not currently in use by the calling process.
Under the hood, the call enforces specific operating semantics. If the named file does not exist, the kernel allocates and initializes it according to the requested permissions, adjusted by the process's file mode creation mask. If the file already exists, creat() does not fail; instead, assuming write permissions are granted, it truncates the existing file's length to zero bytes, effectively wiping its previous contents while retaining its identity on disk. If any error occurs—such as invalid paths, lacking permissions, or an exhausted file table—it returns -1 and sets an error code.
How creat Became Technically Redundant
The irony of creat's permanent survival is that the function itself has been technically redundant for decades. In the earliest editions of Unix, the basic open() system call could only open files that already existed. If a programmer needed to write data to a brand-new file, they had to invoke creat() first to bring the file into being, close it or use the returned descriptor, and then proceed.
This two-tier mechanism was later streamlined when Unix introduced explicit operational flags to the open() system call. By defining access flags such as O_CREAT (create the file if absent) and O_TRUNC (truncate existing files to zero length), the open() call gained the ability to handle both existing and new files in a single unified interface. POSIX specifications document that an invocation of creat(path, mode) is functionally identical to calling open(path, O_WRONLY | O_CREAT | O_TRUNC, mode).
Once open() could create files on demand with flexible read-write options, the dedicated creat() routine was no longer strictly necessary. Yet decades after its operational role was superseded, creat() remains specified, implemented, and active in modern standard C libraries worldwide.
The Power of Backward Compatibility
The reason creat() cannot simply be deleted or renamed illustrates the unyielding momentum of software backward compatibility. Millions of lines of legacy C code, foundational utility programs, and embedded systems were written using the five-letter name. Changing the function name to create() in standard headers or removing creat() altogether would break existing software across every major operating system, from Linux distributions to macOS and BSD variants.
When industry bodies formalized portable Unix standards through POSIX and The Open Group specifications, their explicit goal was to preserve source-code portability for existing programs. Because established software relied on creat(), standardization committees could not alter the spelling. Standardizers documented its equivalence to open(), maintained its legacy syntax, and left the missing letter in place.
This principle creates what engineers call API lock-in. Once an interface is published, widely adopted, and linked into foundational libraries, its cost of replacement rises exponentially. Even a single-letter typo, once elevated into a global interface standard, becomes effectively permanent.
What the Five-Letter Call Left Behind
Ken Thompson's regret serves as an enduring lesson in API design. Modern software architects often treat naming conventions and interface signatures as surface-level details that can be refactored later. But historical computing demonstrates that interfaces outlive the hardware that justified their original compromises.
The PDP-11 computers that necessitated terse identifiers have long been relegated to museums, but modern multi-core servers, mobile devices, and supercomputers still include creat() in their standard system libraries. The truncated word stands as a physical artifact of early computing constraints, preserved untouched in billions of lines of living code.
Key takeaways
•The Unix system call creat() was named without an 'e' due to early computer hardware constraints and identifier length limits in early compilers and linkers.
•The function creat(path, mode) is defined by POSIX standards as precisely equivalent to calling open(path, O_WRONLY | O_CREAT | O_TRUNC, mode).
•Although creat() became redundant once the open() call gained creation and truncation flags, backward compatibility made removing or renaming it impossible.
•Ken Thompson's famous quote—wishing he had spelled creat with an 'e'—highlights how temporary architectural trade-offs can become permanent global standards.