Incident report

The crash twenty seconds intocharacter select.

Players joined, sat at the character screen, and dropped. It happened whether or not anyone went anywhere near the new interior — including with the spawn point nearly three kilometres away. It took a week, and every sensible thing we tried made it look like we were getting closer.

Symptom
Client crash ≈20 s after join
Signature
GTA5+93419F
Time to diagnose
6 days
Root cause
Missing _manifest.ymf

The build was a custom interior in its own resource. It loaded, it looked correct, and you could walk around it. Then players started dropping at character select — not all of them, not instantly, but reliably, around twenty seconds after joining.

Every instinct says this is a problem with the interior. It is not. The most useful early observation was one that seemed to rule the interior out: the crash fires regardless of where the player is. We moved the spawn 2.7 km away and the crash arrived on schedule.

That single fact eliminates almost everything people normally suspect. It is not a draw-distance problem, not a texture budget problem, not a collision problem and not a LOD problem, because none of those can fire for a player who cannot see the building.

Reading the crash properly

Server console will not help you here — the server is fine. The crash is on the client, and the client writes a log:

%localappdata%\FiveM\FiveM.app\logs\CitizenFX_log_*.log
# filenames are UTC — not your local time.
# read the LAST frames before DumpServer starts:

    [  cfx] Crash: GTA5.exe+93419F
    [  cfx] Crash signature: high-sad-wolfram
    [  cfx] Initializing DumpServer

Two practical notes, because both have cost us time. The log filenames are in UTC, so the file you want is often not the one that looks newest relative to your clock. And what matters is the last frames before DumpServer — that is where the crash actually fired. We once spent an afternoon on a misread here, convinced the crash happened on approach to the building, because we read the wrong end of the file.

The week, in order

Each of these was a reasonable hypothesis. Each produced a result that looked like progress. That is what made it expensive.

Day 1
No effect

Blame the exporter

The interior was exported from Blender. The obvious suspect is the exporter, so we rebuilt everything through a different toolchain. The crash was unchanged. We later confirmed the native export had been correct the whole time — an entire tool was suspected, and cleared, for nothing.
Day 2
Correct as-is

Blame the archetype

The interior archetype has a zero bounding box, a zero bounding sphere and an assetless type flag, which looks obviously broken. It is not — that is what a correct MLO archetype looks like, and every reference interior we checked does the same. Time spent fixing something that was never wrong.
Day 3
Inconclusive

Bisect the interior

Strip it down, add pieces back, find the piece that kills it. This is usually the right move and here it produced noise: results that seemed to vary between builds without any change actually mattering.
Day 4
No effect

Blame the names

Renaming files and archetypes to avoid a suspected collision. No change, and by this point the absence of change was the most informative thing we had.
Day 5
Root cause

Read a working interior instead

Rather than continuing to interrogate the broken one, we pulled apart two interiors that are known to work and asked what they had that ours did not. Both shipped a file ours had never contained.

The rule

Every streamed map resource that places archetypes from its own .ytyp must ship a _manifest.ymf. For an MLO, data_file 'DLC_ITYP_REQUEST' in your fxmanifest.lua is not sufficient on its own.

The manifest is what tells the engine which archetype definitions a given map file depends on, so it can resolve them in the right order. Without it, the interior proxy is registered at join — which is why the player’s position is irrelevant — against a type dictionary the engine was never instructed to load first. It is a load-ordering failure wearing the costume of a graphics bug.

This also explains, in retrospect, why the whole first week was wasted. Encoding, layout, geometry and naming were all irrelevant, so every experiment in those categories “failed to reproduce a fix” identically. We were bisecting along an axis the bug did not lie on.

What is actually in a manifest

It is a small binary metadata file with three sections that matter:

For a sense of scale: a large commercial tower we studied ships a manifest with roughly 110 map-dependency entries, because it re-declares the wiring for every vanilla map file its edit touches — not merely its own. It also splits the work across two manifests, one for the building and one for the interiors. That is the standard the finished thing is held to.

Getting one

This is the awkward part, and it is worth saying plainly rather than pretending the tooling is better than it is: the common map-editing library can read these files but cannot write them. There is no save path.

The practical route is to take a manifest from a resource that works, and patch the identifiers inside it to yours. The identifiers are stored as hashes in big-endian order, which is the detail that catches people out — the bytes look wrong if you assume the opposite order and you will conclude the file is corrupt when it is fine. Patch, then dump the result and read it back before you trust it.

How to tell if this is your crash

  1. Players crash a short, fairly consistent interval after joining, rather than at a place.
  2. Moving the spawn far away from the new resource changes nothing.
  3. Removing the resource entirely fixes it, which makes the resource look guilty of something it is not doing.
  4. Re-exporting, renaming and simplifying the interior all have no effect whatsoever.
  5. The resource contains a .ytyp of its own and no _manifest.ymf.

If the first four are true, stop testing the interior. The problem is not in the geometry; it is in what the engine was told about the geometry, and no amount of rebuilding the model will change what it was told.