Bug report
Bug description:
uuid.uuid1() produces UUIDs with corrupted variant bits when called concurrently with the GIL disabled.
The variant bits (byte 8, top 2 bits) should be 0b10 (RFC 4122) but are
observed as 0b11.
Workaround
If uuid._generate_time_safe is called at least once at import time, issue is no longer reproducible.
Reproduction
import os
import platform
import subprocess
import sys
import threading
import time
import uuid
THREADS = 32
SECONDS = 0.01
BATCH = 1024
RUNS = 1000
def valid_bytes(data):
return (data[6] >> 4) == 1 and (data[8] & 0xC0) == 0x80
def print_corrupted(data, call_number):
masked = data[:10] + b"\xcc" * 6
v = uuid.UUID(bytes=masked)
label = "FIRST CALL" if call_number == 1 else f"call #{call_number}"
print(
f"Bug reproduced on {label}:\n"
f" {v = !r}\n"
f" {v.bytes.hex() = !r}\n"
f" {v.clock_seq_hi_variant = }\n"
f" {v.version = !r}\n"
f" {v.variant = !r}\n"
f" variant_bits: {bin(masked[8] >> 6) = }\n"
f" {v.is_safe = !r}\n"
)
def worker_main(mode):
generate_time_safe = getattr(uuid, "_generate_time_safe", None)
if generate_time_safe is None:
print("uuid._generate_time_safe is not available")
raise SystemExit(2)
raw_mode = mode == "uuid._generate_time_safe"
stop = threading.Event()
barrier = threading.Barrier(THREADS + 1)
corrupted = []
def thread_main():
barrier.wait()
call_number = 0
end = time.perf_counter() + SECONDS
while time.perf_counter() < end and not stop.is_set():
for _ in range(BATCH):
call_number += 1
if raw_mode:
data, _ = generate_time_safe()
ok = valid_bytes(data)
else:
v = uuid.uuid1()
data = v.bytes
ok = v.version == 1 and v.variant == uuid.RFC_4122 and v.is_safe
if not ok:
corrupted.append((data, call_number))
stop.set()
break
threads = [threading.Thread(target=thread_main) for _ in range(THREADS)]
any(t.start() for t in threads)
barrier.wait()
any(t.join() for t in threads)
if corrupted:
data, call_number = corrupted[0]
print_corrupted(data, call_number)
raise SystemExit(1)
def run_mode(mode):
env = {**os.environ, "PYTHON_GIL": "0"}
print(f"\nTrying: {mode}")
for run in range(1, RUNS + 1):
result = subprocess.run(
[sys.executable, __file__, "worker", mode],
env=env,
text=True,
capture_output=True,
)
if result.returncode:
print()
print(result.stdout.strip())
if result.stderr.strip():
print(result.stderr.strip())
return result.returncode
print("Run: ", run, end="\r")
print("No failure after", RUNS, "runs")
return 0
def master_main():
print(f"Python: {sys.version.replace(chr(10), ' ')}")
print(f"GIL: {getattr(sys, '_is_gil_enabled', lambda: 'unknown')()}")
print(f"Platform: {platform.platform()}")
print(f"Machine: {platform.machine()}")
print(f"CPU: {platform.processor()}")
print(f"CPU_COUNT: {os.cpu_count()}")
print(f"uuid._generate_time_safe: {getattr(uuid, '_generate_time_safe', None)}")
r1 = run_mode("uuid._generate_time_safe")
if not r1:
print(f"\nplain `_generate_time_safe` did not reproduce")
else:
print(f"\nplain `_generate_time_safe` reproduced; now checking public uuid.uuid1()")
r2 = run_mode("uuid1")
raise SystemExit(r1 or r2)
if __name__ == "__main__":
if len(sys.argv) > 1 and sys.argv[1] == "worker":
worker_main(sys.argv[2])
else:
master_main()
Python: 3.14.3 free-threading build (main, Mar 10 2026, 18:06:03) [Clang 21.1.4 ]
GIL: False
Platform: macOS-15.0.1-arm64-arm-64bit-Mach-O
Machine: arm64
CPU: arm
CPU_COUNT: 8
uuid._generate_time_safe: <built-in function generate_time_safe>
Trying: uuid._generate_time_safe
Bug reproduced on call #2:
v = UUID('c864280e-57c0-11f1-e2b2-cccccccccccc')
v.bytes.hex() = 'c864280e57c011f1e2b2cccccccccccc'
v.clock_seq_hi_variant = 226
v.version = None
v.variant = 'reserved for future definition'
variant_bits: bin(masked[8] >> 6) = '0b11'
v.is_safe = <SafeUUID.unknown: None>
plain `_generate_time_safe` reproduced; now checking public uuid.uuid1()
Trying: uuid1
Run: 18
Bug reproduced on FIRST CALL:
v = UUID('c9c58206-57c0-11f1-d967-cccccccccccc')
v.bytes.hex() = 'c9c5820657c011f1d967cccccccccccc'
v.clock_seq_hi_variant = 217
v.version = None
v.variant = 'reserved for Microsoft compatibility'
variant_bits: bin(masked[8] >> 6) = '0b11'
v.is_safe = <SafeUUID.unknown: None>
CPython versions tested on:
3.14.3t, 3.15t
Operating systems tested on:
macOS, Linux
Bug report
Bug description:
uuid.uuid1()produces UUIDs with corrupted variant bits when called concurrently with the GIL disabled.The variant bits (byte 8, top 2 bits) should be
0b10(RFC 4122) but areobserved as
0b11.Workaround
If
uuid._generate_time_safeis called at least once at import time, issue is no longer reproducible.Reproduction
CPython versions tested on:
3.14.3t, 3.15t
Operating systems tested on:
macOS, Linux