mojira.dev
BDS-23105

BDS 1.26.45.1: 0xC0000409 abort in Streaming Pool chunk worker (std::system_error on unlock)

SHORT DESCRIPTION

The server process terminates with exit code 0xC0000409 (STATUS_STACK_BUFFER_OVERRUN as reported by the CRT fail-fast path; it is actually abort() called from std::terminate). Nothing is printed to the console; the last log lines are normal gameplay/startup lines. Windows Error Reporting writes a minidump each time.

Frequency on our production server: 61 crashes on 2026-08-29, 16 on 2026-09-03, 4 on 2026-09-04. It happens both with players online (most often right after a player joins / moves through many chunks, or after WorldEdit-style bulk block changes) and with NO players at all (2026-09-04 15:00: three consecutive crashes 7-8 seconds after "Server started." during a scheduled restart, 0 players connected). Exact version: 1.26.45.1 (not selectable in the version field above). Same crash seen on 1.26.44.3 and, less frequently, since about 1.26.32.

WHAT THE MINIDUMPS SHOW (10 dumps, identical signature)

- Exception 0xC0000409, parameter 7 (FAST_FAIL_FATAL_APP_EXIT) at ucrtbase!abort+0x4e

Faulting thread name: "Streaming Pool(0)"

Unwind chain on that thread: ntdll!RtlRaiseException -> KERNELBASE!RaiseException -> VCRUNTIME140!_CxxThrowException -> ucrtbase!__C_specific_handler_noexcept -> ucrtbase!terminate -> ucrtbase!abort, i.e. a C++ exception thrown inside a noexcept frame.

The ThrowInfo referenced from the stack resolves (RTTI in bedrock_server.exe) to std::system_error (bases std::_System_error, std::runtime_error, std::exception).

The throwing function (bedrock_server.exe+0x1D9E30 in 1.26.45.1) is the unlock routine of a recursive-lock object: it calls MSVCP140!_Thrd_id, FNV-1a-hashes the thread id, compares it with the stored owner hash at [this+0x10]; when the calling thread is not the owner it constructs std::system_error(std::errc::operation_not_permitted, generic_category()) and throws. So the lock is acquired on one thread and released on another (or released twice).

Functions being unwound (identified by the strings they reference): Bedrock::NonOwnerPointer<WorkerPool>::_get, ChunkSource::_launchGenerationTask(const std::shared_ptr<LevelChunk>&, bool), ChunkSource::_launchStructurePostProcessingTask(...), LevelChunk stage functions referencing "LevelChunk" + "ReplaceChunk" / "LoadChunk" / "DecorationPostProcess" / "StructurePostProcess" / "InitialLighting" / "Chunk Relight", "Loading levelchunk {} {} from savegame", BlockTypeRegistry::getDirectAccessBlocks, and the worker loop "Worker - Run one task". Profiler labels "Chunk Gen", "Chunk Structure PP", "Chunk PP", "Chunk CFRD", "Chunk Neighbor Upgrade" are referenced by the same function.

One lab run died with 0xC0000374 (heap corruption) instead, which suggests a data race / lifetime issue in the chunk pipeline rather than a pure logic error.

STEPS TO REPRODUCE (no players needed)

1. Copy the server folder and the world. Take the world copy while the server is running (so LevelDB has to recover its log on the next open), or use a world left behind by a previous crash.

Start bedrock_server.exe (packs enabled or disabled - disabled crashes faster).

Immediately after "Server started.", force chunk loading from the console: every ~3 s add 10 ticking areas (tickingarea add <x1> 64 <z1> <x1+159> 64 <z1+159> labN, i.e. 100 chunks each, random positions inside the generated area), optionally a few fill commands, then tickingarea remove_all; repeat. (The attached labrun.py / labbatch.py do exactly this.)

The process exits with 0xC0000409 after 9-40 seconds in roughly half of the attempts (with all packs disabled: 6 of 7 attempts, always ~9 s). Before dying the server stops answering console commands for up to ~50 s.

Control: starting the same world and doing nothing (start -> wait 30 s -> stop, 22 attempts) never crashes; the same load on a cleanly closed world crashed 0 of 4 times in 8-10 minutes. So the crash needs concurrent chunk loading while the storage layer is busy (log recovery / compaction).

EXPECTED RESULT

The server keeps running. A lock must not be released on a different thread than it was acquired on in the chunk pipeline (or the exception must not escape a noexcept task).

ACTUAL RESULT

Process abort with 0xC0000409; all players are disconnected.

ATTACHMENTS

- crash_dumps.zip: 4 minidumps (bedrock_server.exe 1.26.45.1) - 2 from production with players, 2 from production with 0 players (2026-09-04 15:00 / 15:32)

crash_2026*.log: last console output before each of 4 crashes

server.properties.txt, world_behavior_packs.json

lab_repro/labrun.py, labbatch.py, labboot.py: reproduction scripts; lab_b1_nopack_1749.log: console log of a 9-second crash with all packs disabled

The 1.2 GB world can be provided on request.

Environment

Windows 11 Home 26200 x64, i9-13900KF (32 threads), 32 GB RAM, NVMe SSD. Vanilla bedrock_server.exe 1.26.45.1. Flat world, ~362k chunks (1.2 GB LevelDB). view-distance=12, tick-distance=4, max-threads=2 (0/1/8 also tested).

Attachments

Comments 1

Thank you for helping us improve Minecraft! We saved your files:

[media][media][media][media][media][media][media][media][media][media][media][media]

AOIROSERVER

(Unassigned)

Unconfirmed

Retrieved