Vog |>
Why Vog Footguns Glimpse Blog
|> THE FOOTGUN CATALOG

We catalogued the ways a language lets you fail.

Thirty-two highlighted classes of bug that a language's design can enable, grouped by the Vog decisions that retire them. The comparison table narrows that catalog to the eighteen most load-bearing rows, then shows how Vog answers them without pretending every row has the same weight.

32 highlighted classes
18 compared rows
6 design invariants
15 languages compared
HOW TO READ A ROW
Three honest bands. Never flattened into “all eliminated.”

The page highlights thirty-two classes under six design invariants; the field comparison uses eighteen representative, load-bearing rows. A category can be closed more than one way, and the difference is the whole point. Collapsing them into a single brag is exactly the dishonesty this catalog exists to avoid.

Unrepresentable
The feature doesn't exist. The mistake has nothing to attach to — you can't write it down.
Caught at compile time
Expressible, but it won't build. The compiler or type system rejects the dangerous combination.
Minimized
An idiom backed by visible types, not yet a hard invariant. Bypassing it is a code error you can see, not a silent trap.
ONE INVARIANT KILLS MANY CLASSES

A small set of deep decisions, not disconnected features.

Each invariant below retires several rows of the catalog at once. That coherence is why the result doesn't feel like a pile of special cases.

01 Immutability & no shared mutable state
Full immutability makes aliasing harmless by construction.
Data racesAliasing bugsLost updatesMutable-default surpriseLate-binding capture
02 Managed memory and checked collections
No manual allocation model, no buffer corruption path, and collection access is loud when it can fail.
Manual memory managementBuffer overflowImplicit resource finalization
03 Ok/Ng plus exhaustive case
Failure travels as a value; every branch must be handled.
Null dereferenceUnhandled errorsSilent error-swallowingIncomplete error contractsNon-exhaustive matchHidden exception control flow
04 No reflection, no macros
What you read is what executes.
Macro opacityRuntime-reflection surpriseHidden dynamic dispatch
05 Bignum Int and Decimal by default
The numeric footguns have nowhere to originate.
Silent integer overflowFloat-money roundingNaN / Infinity poisonDivide-by-zero crashNumeric precision lossOperator-precedence traps
06 Strong static types + one closed escape hatch (Term)
No any-spreading, no stringly-typed APIs, no silent coercion.
Implicit coercionTruthinessStringly-typed / injectionText / bytes confusionUnsafe castsType-erasure mixingIll-defined orderingInexact hash keysShadowing
THE SHOWPIECE

Vog against the field, and its nearest relatives.

The eighteen most load-bearing error classes against eleven mainstream languages plus Elixir, Gleam, and Zig. A judgment summary of each language's defaults, not its most-disciplined possible use — a shop running only prepared statements, -Wshadow, and the race detector lands better than its column suggests.

Y closed / safe by design ~ partial, opt-in, or mitigated N enabled by default
Error classPyJSTSJavaC#CC++GoRustSwiftRubyElixirGleamZigVog
HIGH SEVERITY · corruption, exploit primitive, data loss
Memory safety
Y
Y
Y
Y
Y
N
N
Y
Y
Y
Y
Y
Y
~
Y
Injection-safe sinks
N
N
N
N
N
N
N
~
N
N
N
~
N
N
~
Null safety
N
N
~
N
~
N
N
N
Y
Y
N
~
Y
Y
Y
Array-bounds safety
Y
~
~
Y
Y
N
N
Y
Y
Y
~
Y
Y
~
Y
Data-race prevention
~
Y
Y
N
N
N
N
N
Y
~
~
Y
Y
N
Y
Fully defined (no UB)
Y
Y
Y
Y
Y
N
N
Y
Y
Y
Y
Y
Y
~
Y
Integer-overflow safety
Y
~
~
N
N
N
N
N
~
Y
Y
Y
~
Y
Y
CORRECTNESS & RELIABILITY · silent-wrong answers, control-flow integrity
Arithmetic / calc errors
~
N
N
~
~
N
N
~
~
~
~
~
~
~
Y
Mandatory error handling
N
N
N
~
N
N
N
~
Y
~
N
~
Y
Y
Y
No hidden exceptions
N
N
N
N
N
Y
N
~
Y
Y
N
~
Y
Y
Y
Error-contract complete
N
N
N
~
N
N
N
N
~
~
N
N
Y
Y
Y
Exhaustive matching
N
N
~
~
~
N
~
N
Y
Y
N
~
Y
Y
Y
Immutable by default
N
N
N
N
N
N
N
N
Y
~
N
Y
Y
N
Y
No implicit coercion
~
N
~
~
~
N
N
Y
Y
Y
~
~
Y
Y
Y
REASONING & HYGIENE · legibility, maintainability
No reflection surprise
N
N
N
N
N
Y
~
~
Y
~
N
N
Y
Y
Y
No macro surprise
N
N
N
~
~
N
N
Y
N
~
N
N
Y
~
Y
Shadowing controlled
N
N
N
~
~
N
N
N
~
~
~
~
~
Y
Y
Simple op-precedence
N
N
N
N
N
N
N
~
N
N
N
N
~
~
Y
Bands are scored separately and never summed across — a flat total would let a language close low-stakes rows, leave null and memory open, and still out-score one that closed only those. Within a band, Y = 1 and ~ = 0.5. Read a band score as a position in a regime, not a measurement.

The banded tally.

On the high-severity band that matters most, the field compresses hard: Vog leads, but Rust, Swift, Gleam, and Elixir sit close behind, and even the memory-safe dynamic languages land within a point — because GC, bignum integers, and defined semantics already retire several rows for them. The honest read: Vog leads its nearest relative on all three bands, but the lead is one point or less, and it's widest exactly where the stakes are lowest.

LanguageHigh severity /7Correctness /7Hygiene /4
Vog
6.5
7.0
4.0
Gleam
5.5
6.5
3.0
Rust
5.5
6.0
1.5
Swift
5.5
5.0
1.5
Elixir
5.5
3.5
0.5
TypeScript
4.5
1.0
0.0
Python
4.5
1.0
0.0
Ruby
4.0
1.0
0.5
JavaScript
4.0
0.0
0.0
Zig
3.5
5.5
3.0
Go
3.5
2.5
2.0
C#
3.5
1.5
1.0
Java
3.0
2.5
1.0
C
0.0
1.0
1.0
C++
0.0
0.5
0.5
THE HONEST SHAPE

What Vog does not close.

Stripping away the categories Vog closes leaves a short, honest list. Naming it is the point — a catalog that only listed wins would be marketing, not rigor.

Injection at third-party sinks
For sinks the stdlib owns, injection is mechanically inexpressible. For sinks it doesn't, the guarantee drops to a loud, typed escape hatch and the convention to use it — the same posture Java takes toward prepared statements. Idiom not yet promoted to invariant; a visible code error, not a silent hole.
Concurrency beyond data races
Share-nothing message passing closes data races outright. It does nothing for logical races, lost updates, or mailbox backpressure, and deadlock is relocated (to synchronous call cycles) rather than eliminated. “No data races” must not be read as “concurrency-safe.”
TOCTOU & external-world races
Check a file exists, then read it; it changed in between. Out of reach for any language — a deployment and supervision concern. The model at least surfaces the failure rather than hiding it.
Performance non-locality
Bignum Decimal work and String assembly allocate behind ordinary-looking calls. Not a safety bug; the defense is tooling, not the type system. Worth instrumenting, not worth contorting the language for.
IF THIS SOUNDS TOO GOOD TO BE TRUE
The unvarnished version.
This page is the marketing-shaped cut. The raw write-up — a bias-flagged benchmark that does not try to make Vog look best, with every contested cell argued and the author's thumb on the scale called out — is exactly what it is. No spin.
the raw analysis note |> coming posted to Bluesky when it lands

The repo isn't open yet. The work is out in the open.

Vog is still in design — the repository isn't open yet, but it will be under appropriate open source licenses. No mailing list, no launch date; just the thinking, shared in the open until the code and compiler are ready to share.

LANGUAGE SPEC 85%
COMPILER 60%
follow the build on bluesky |>
Vog |>
Blog
a statically typed, immutable language for the AI coding agent era · in design |> coming soon