Why your MongoDB UUID looks different - cover art

MongoDB and UUID 12 min read

Why your MongoDB UUID looks different (same logical ID, different hex)

June 24, 2026 · 12 min read

You copied a UUID from MongoDB Compass, pasted it into a Slack thread, dropped it into a C# unit test, and suddenly three people insist they are “different IDs.” Often they are not different at all - they are the same 128-bit value shown through different lenses: BSON subtype 03 versus 04, base64 Extended JSON, uppercase versus lowercase strings, or a hex dump of raw bytes versus a canonical RFC string. This guide catalogs the innocent reasons MongoDB UUIDs look different so you can stop chasing phantom data corruption.

One logical UUID, many legitimate representations

At the logical layer, a UUID is 128 bits. Everything else is encoding. Canonical string form adds hyphens and hex digits. Compact form removes hyphens. URNs add a prefix. BSON Binary stores sixteen octets plus metadata. Base64 wraps those octets for JSON transports. A developer comparing only strings may think two values differ when a bytewise comparison would show equality after normalization.

Establish team vocabulary: “logical UUID” means the 128-bit value; “representation” means how it is serialized. Incidents close faster when logs state both representation and subtype.

Subtype 03 vs 04 makes hex diverge

The most common MongoDB-specific surprise is endianness in the first twelve bytes. Compass may show a friendly canonical string while the underlying hex for subtype 03 differs from subtype 04. Both strings can be “correct” relative to their codec. Comparing hex from mongodump to hex from a Java UUID without conversion is an apples-to-oranges diff.

Canonical string (both codecs aim to display this):
550e8400-e29b-41d4-a716-446655440000

Subtype 04 hex payload (RFC byte order):
550e8400e29b41d4a716446655440000

Subtype 03 hex payload (legacy GUID order) - first 12 bytes permuted

When someone says “Mongo changed my UUID,” ask which layer changed: payload bytes, subtype byte, or only the string casing in a log formatter.

Display formatting versus stored bytes

MongoDB shell and Compass optimize for human readability. They may uppercase hex in some views while your API returns lowercase. JSON serializers might emit UUID strings with braces because they copied .NET defaults. None of these change the database value if drivers wrote correct binary - but they change what you see in a screenshot.

Binary fields copied into UTF-8 text files sometimes show replacement characters or mojibake; that is encoding damage, distinct from endianness. If the paste looks like garbage, inspect hex directly.

How different tools show the same field

mongodump Extended JSON uses $binary with base64. Datadog might log canonical strings. Snowflake might store FIXED(16) without hyphens. Each is convertible, but automated diff tools that string-compare without BSON awareness will flag false positives.

Driver major versions occasionally change default UUID representation settings; upgrading without reading release notes looks like “MongoDB started generating different UUIDs” when the app started writing a different subtype.

A checklist before you open a Sev-1

First, normalize both sides to canonical lowercase strings with a subtype-aware converter. Second, compare raw sixteen-byte buffers. Third, confirm collection codec settings in .NET or Java. Fourth, verify you are not comparing a string _id field to a binary _id field. Fifth, check whether one path uses UUID v4 random bytes while another regenerated the ID entirely - those are genuinely different IDs.

Document findings in the incident channel with hex, subtype, and tool versions. Future you will thank present you when the same confusion resurfaces after the next driver upgrade.

Teach support engineers a single phrase: “normalize to canonical string with subtype-aware tooling before declaring mismatch.” That one habit eliminates most false escalations where screenshots disagree but databases agree.

Remember that UUID v7 and other time-ordered variants still occupy sixteen bytes; only the bit layout changes. A “different looking” v7 string is not endianness - it is a different version nibble - so always read the version field before blaming MongoDB storage.

Screenshot-based debugging fails when tools strip leading zeros or wrap long hex lines. Prefer copying machine-readable Extended JSON from the source system rather than retyping from images in chat, which introduces transcription errors that masquerade as endianness problems.

Add a short “UUID representation” section to your service README listing BSON subtype, driver version, and sample canonical ID so new engineers do not rediscover the same Compass-versus-Postman confusion on day one.

When pairing with QA, provide fixture documents in Extended JSON so test cases assert on decoded strings while automation can still validate raw subtype in the database - two views of one truth, documented upfront.

FAQ

Does uppercase vs lowercase mean different UUIDs?
No for logical equality if hex digits match. Comparators should normalize case before string compare.
Why does base64 not match the string?
Base64 encodes the 16-byte payload, not the hyphenated text. Decode base64 to bytes, then format as canonical string.
Can Compass be wrong?
Compass displays decoded values. Misconfiguration is rare; mismatched expectations between Compass and a legacy app are common.
When are two UUIDs actually different?
When the 128-bit values differ after both are normalized to the same byte order - not when only presentation differs.

Related: Fixing endianness · Binary UUID explained · Subtype comparison · UUID converter

Browse all tools