docs(04-mods): record first-cutover deploy gotchas

Document the two crash classes hit on first deploy: NeoForge pin must match
the distribution's version, and client-only mods that declare BOTH crash the
dedicated server with "invalid dist DEDICATED_SERVER" (tomllib can't catch
them — hand-set to client + re-sync). Mark the decommission checklist done;
flag the landing join-flow rework as the one remaining open item. Current
state: 24 client / 52 both.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-10 01:16:48 +02:00
parent c249172baa
commit 096ef82420

View File

@@ -147,24 +147,64 @@ in the deploy path (keeps deploy offline + deterministic).
## Decommission checklist (on execution) ## Decommission checklist (on execution)
- [ ] `tooling/classify-mods.py` + generate initial `mods-sides.json` (review it). Done at first cutover (commits `27237bc`, `84196d5`, `c249172`):
- [ ] `tooling/sync-server-mods.sh`. - [x] `tooling/classify-mods.py` + generated initial `mods-sides.json`.
- [ ] compose: drop `PACKWIZ_URL`, `pack.` extra_host, `./pack`/`./custom` mounts, - [x] `tooling/sync-server-mods.sh`.
`pack.` caddy vhost; add `server-mods` mount + `REMOVE_OLD_MODS`. - [x] compose: dropped `PACKWIZ_URL`, `pack.` extra_host, `./pack`/`./custom`
- [ ] delete `tooling/render-pack.sh`; remove its call from docs/deploy. mounts, `pack.` caddy vhost; added `server-mods` mount + `REMOVE_OLD_MODS`.
- [ ] delete `pack/` (pack.toml, index.toml, `*.pw.toml*`, `.packwizignore`, - [x] deleted `tooling/render-pack.sh` (+ dead `add-custom-mod.sh`).
CustomSkinLoader templates if duplicated in DIST) and `custom/` (jars now - [x] deleted `pack/` and `custom/` (jars now sourced from `$DIST`).
sourced from `$DIST`). - [x] `.gitignore`: dropped packwiz lines; added `server-mods/`.
- [ ] `.gitignore`: drop packwiz lines; add `server-mods/`. - [x] superseded `plan/04-packwiz.md`; updated `05-minecraft.md`, `14-deploy.md`,
- [ ] supersede `plan/04-packwiz.md`; update `05-minecraft.md`, `14-deploy.md`, `CLAUDE.md`.
`CLAUDE.md` (mod source section), and the landing join steps if they still - [x] resolved the host-local divergence around `pack/`
reference `pack.toml`. ([[cochi-host-local-divergence]]).
- [ ] resolves the host-local divergence around `pack/` ([[cochi-host-local-divergence]]). - [ ] **STILL OPEN (roadmap):** landing join steps still reference the dead
`pack.toml` URL (`site.ts packwizUrl`, `i18n/ui.ts` step 3) — rework around
the HeliosLauncher/`distribution.json` flow.
- [x] deployed to `cochi`: NeoForge bumped to 21.1.233, 52 server mods, `Done`,
mc-status `online:true`.
## Deployment gotchas (learned 2026-06-10, first cutover)
### NeoForge version MUST match the distribution
The distribution's mods are built against a specific NeoForge (in
`distribution.json``21.1.233`). Several hard-require it (ferritecore ≥21.1.218,
farmersdelight ≥21.1.219, configured ≥21.1.211). A lower `NEOFORGE_VERSION` pin
fails pre-load with `Missing or unsupported mandatory dependencies: neoforge`.
Keep `docker-compose.yml`'s pin in lockstep with the distribution on every mod
update.
### Client-only mods that declare `BOTH` crash the dedicated server
tomllib classifies by the `minecraft`/`neoforge` dependency `side`. Mods that
declare **`BOTH`** but are actually client-only (touch `net.minecraft.client.*`)
pass through as `both`, load on the server, and crash hard:
```
java.lang.RuntimeException: Attempted to load class
net/minecraft/client/gui/screens/Screen for invalid dist DEDICATED_SERVER
- <Mod> has failed to load correctly
```
This is **not** mere RAM waste — it's a fatal crashloop. tomllib cannot detect
it (the manifest lies). **Fix = hand-set the mod to `client` in
`mods-sides.json`, re-sync, recreate minecraft.** First cutover required marking
these (leaf client-GUI mods, nothing server-loaded depends on them):
`BetterF3, JustEnoughResources, MouseTweaks, Searchables, TravelersTitles,
drippyloadingscreen, entityculling, fancymenu, konkrete, melody, ponderjs,
welcomescreen, yeetusexperimentus` — on top of the 11 tomllib auto-caught
(sodium, sodium-extra, iris, ImmediatelyFast, appleskin, Controlling, BridgingMod,
CustomSkinLoader, entity_model_features, entity_texture_features, tagtooltips).
**Current state: 24 `client` / 52 `both`.** The 52 may still hide a client-only
mod that loaded without crashing; if a future restart trips another
`invalid dist DEDICATED_SERVER`, flip that one jar to `client` and re-sync — same
one-line loop. When excluding, prefer leaf mods; if a `both` mod hard-depends on
the one you exclude you'll get a `Missing mandatory dependency` instead — put it
back.
## Open questions / risks ## Open questions / risks
- **Cosmetic-client mods** load on the server unless manually set `client` — RAM
waste, not a crash. Curate `mods-sides.json` over time.
- **No manifest** in a jar → defaults `both`. Acceptable; review the defaulted - **No manifest** in a jar → defaults `both`. Acceptable; review the defaulted
list `classify-mods` prints. list `classify-mods` prints.
- **Nebula regen** may rename jars (version bumps) → `mods-sides.json` keys go - **Nebula regen** may rename jars (version bumps) → `mods-sides.json` keys go