Resource Pack Manager Troubleshooting
This page only covers behavior that is currently confirmed in the ResourcePackManager codebase.
The single most useful first step for any RSPM issue is:
/rspm status
It prints version, deploy mode (standalone vs network-backend), a short non-secret network key fingerprint plus where that key came from, Java + Bedrock pack state, the active delivery path with URL, the resolved external host + auto-detected public IP, all relevant config flags, a proxy-deployment reminder (the network proxy jar is the same ResourcePackManager.jar), and Floodgate / Geyser-Spigot detection. The same command exists when the jar runs on a proxy and prints proxy-side equivalents (backend list, per-backend fetch outcomes, merged-pack state).
The console is quiet on purpose
RSPM prints one line each time it freshly initializes a delivery path — the outcome:
[ResourcePackManager] Resource pack is live via self-hosting — http://play.example.com:25566/rspm.zip
[ResourcePackManager] Resource pack is live via automatic hosting — https://magmaguy.com/rsp/<uuid>
Everything else — each pack staged, each cluster merged, each stability check, each self-host probe and its result — is suppressed by default. A condition RSPM recovers from on its own is not reported as a warning. If a self-host probe fails and RSPM silently switches to remote hosting, that is a success, not a fault, and the console says nothing about it.
So: an absence of warnings is not evidence that nothing happened, and the presence of the outcome line means players are getting a pack. Before reporting a hosting or merging bug, turn the narration on:
/rspm verbose on
then /rspm reload. That command writes verboseLogging: true into plugins/ResourcePackManager/config.yml for you and the setting survives restarts, so /rspm verbose off when you're done. Editing the key by hand does the same thing. The Bedrock converter has a separate switch, bedrockConverterDebug, which is config-only.
Warnings you can legitimately see are genuine faults: repeated pack-delivery failure to a specific player, a client reporting INVALID_URL, an HTTP port that could not bind, both delivery paths failing, or a proxy that has polled several cycles without any backend producing content.
Players are not receiving the resource pack
Check these first:
autoHostmust be enabled if you want normal automatic delivery (selfHostForceis the explicit testing override)- the merged pack must exist and at least one delivery path (self-host or remote) must have succeeded
- players only receive the pack on join, or via the first-upload broadcast that fires the moment hosting becomes ready
- Floodgate players are intentionally skipped by Java delivery because Geyser owns their Bedrock pack session
If needed:
- Run
/rspm statusand look at the "Hosting" section.Active deliveryshows whether self-host, remote, or neither is currently in use. - If "active delivery: not yet ready" — the mix or upload is still in progress. The plugin loud-banners this in the console when a player joins too early and will auto-send the pack the moment delivery is ready.
- If "active delivery: none — hosting disabled or failed" —
autoHostis off, or self-host probes and remote upload both failed. See "Self-host sanity checks failed" and "Auto-hosting cannot reach the remote server" below. - Set
verboseLogging: true, run/rspm reload, watch console for the upload / self-host probe results, then rejoin with a test player. (Without that flag the probe steps are not printed — only the final "Resource pack is live via ..." outcome line is.)
The join offer is delayed by about one second. If a Java client reports FAILED_DOWNLOAD or DISCARDED, RSPM retries automatically up to three attempts for that player session. It does not retry a player decline or an INVALID_URL; repeated retry exhaustion and invalid URLs are logged as real faults.
If you are self-hosting through your own external pipeline (autoHost: false), RSPM does not push your custom URL for you. In that setup you still need your own server-side pack delivery flow.
ItemsAdder is installed, but its content is missing from the final pack
This usually means ItemsAdder is still configured in a way that prevents ResourcePackManager from reading or hosting its output.
Use:
/rspm itemsadder configure
That command currently:
- enables
resource-pack.hosting.no-host.enabled - disables
protection_1,protection_2, andprotection_3 - sets
resource-pack.zip.compress-json-files: false - runs
/iareload, then/iazip - reloads ResourcePackManager about 15 seconds later
If the command tells you ItemsAdder is already hosting its own pack, disable ItemsAdder hosting manually first and run the command again.
The merged pack is invalid or fails to upload
ResourcePackManager's auto-host integration explicitly handles these server-side error types:
- missing required files
- file too large
- invalid file format
- missing session
- remote server unavailable
If you hit one of these:
- Run
/rspm reloadto rebuild the pack. - Check whether one of the source packs is malformed, encrypted, or otherwise unreadable.
- Check whether the final merged pack still contains a valid
pack.mcmetaandpack.pngat the root.
If an enabled pack cannot be extracted or staged, the current mix aborts and the console names the failing pack. Repair that pack, remove a manually added ZIP, or set isEnabled: false in its automatic integration config before reloading.
One broken pack no longer blocks everything forever
A pack that cannot be staged fails the same way on every retry, so left alone it would wedge delivery permanently — the merge never completes and the same error repeats indefinitely. After three consecutive failures of the same file, RSPM drops that pack from the merge so the remaining packs can ship, and says so once, loudly:
[ResourcePackManager] Resource pack X.zip failed to stage 3 times in a row and has been excluded
from the merge so the remaining packs can be delivered. The merged pack is now INCOMPLETE ...
Read that as intended: players are now getting a pack that is missing that plugin's content. The usual cause is a corrupt or partially written zip.
The exclusion clears itself. The failure record is keyed on the file's size and modification time, so repairing or replacing the file automatically retires the quarantine and the pack rejoins the next merge — no command, no restart. /rspm reload also resets all quarantine records from scratch. Failure counts that never reached three are dropped after any successful mix, so unrelated transient hiccups spread over a long uptime cannot accumulate into an exclusion.
On a SESSION_NOT_FOUND error from the remote auto-host, RSPM clears its session UUID and re-initializes on the next keep-alive tick — no manual intervention required.
One plugin's assets are overriding another plugin's assets
This is controlled by priorityOrder in:
plugins/ResourcePackManager/config.yml
Higher entries win over lower entries.
For non-mergeable files, ResourcePackManager replaces the lower-priority file. For mergeable JSON files, it merges content instead. The currently mergeable JSON categories are:
sounds.json- language files
- vanilla item model JSON in
minecraft/models/item(non-recursive merge: only theoverridesarray is combined across packs, the rest of the file follows highest-priority-wins) - atlas files
- font files
- 1.21.4+ item model definitions in
items/(format-aware merge that respects predicate-tree structure)
pack.mcmeta is also merged specially: the highest pack_format wins, supported_formats ranges are widened (integer, two-int array, and {min_inclusive, max_inclusive} object forms are all supported), overlay entries are combined, and non-standard top-level keys are preserved. Overlay entries are normalized for 1.21.9+ compatibility by adding min_format/max_format fields when missing. Base atlas sources are also merged into overlay atlas files to prevent overlays from shadowing base entries.
If you need to inspect what happened during the last merge, check:
plugins/ResourcePackManager/collision_log.txt
GUI text or font-based elements look wrong
Font files are one of the JSON categories ResourcePackManager merges, but that does not guarantee two different font systems will behave well together in Minecraft.
If a font-driven menu or HUD looks wrong:
- Change
priorityOrderso the pack you want to win is higher. - Run
/rspm reload. - Check
collision_log.txtto confirm collisions happened where you expected.
Resource pack changes are not showing up immediately
ResourcePackManager has a watchdog for supported pack sources.
It waits until a changed pack remains unchanged for 3 seconds, then once all watched packs are stable the remix happens immediately.
If you are actively regenerating another plugin's pack, give it a few seconds after file writes stop. If in doubt, run /rspm reload after the upstream plugin finishes.
/rspm status says remote hosting, but I expected self-host
This is normal behaviour when preferSelfHost: true (the default) and one of the three self-host sanity checks failed. RSPM does not warn about this — falling back to remote hosting is a successful outcome, so the failed check is logged at detail level with an explicit "This is OK." and stays hidden unless verboseLogging: true. The only line you get by default is Resource pack is live via automatic hosting — ....
Run /rspm verbose on (or set verboseLogging: true) and /rspm reload to see which of the three layers failed:
- Layer 1 (heuristic) — the resolved external host is RFC1918 / loopback / link-local. Either set
selfHostExternalHostto your real public hostname, or ensure the plugin can reach api.ipify.org / checkip.amazonaws.com. - Layer 2 (localhost self-probe) — a HEAD request to
http://127.0.0.1:<port>/rspm.zipdid not return 200 with a non-empty body. Catches port-bind collisions or missing pack files. - Layer 3 (external reachability probe) — magmaguy.com tried to fetch your announced URL and couldn't reach it. Most commonly: the HTTP port isn't forwarded at the router / firewall. The probe URL and a reason code (
PRIVATE_HOST_REJECTED,CONNECT_TIMEOUT,ECONNREFUSED,RATE_LIMITED, ...) are printed underverboseLogging.
Fixes (in order of preference): open the HTTP port at your firewall + router, set selfHostExternalHost to a routable hostname, or set preferSelfHost: false to skip self-host entirely.
When the magmaguy.com probe is itself unreachable (RSPM can't talk to it to ask), self-host is kept rather than failed — the rationale being that the fallback path needs magmaguy.com too, so refusing to commit on inability-to-probe would be paradoxical.
See Self-hosting for the full decision tree.
Auto-hosting cannot reach the remote server
ResourcePackManager's built-in remote host talks to:
https://magmaguy.com/rsp/
If that connection fails, the plugin logs communication warnings and cannot use the remote fallback until it reconnects successfully.
Your options are:
- fix the server's outbound HTTPS connectivity
- wait for the remote service to become reachable again
- disable
autoHostand host the generated zip yourself - open your HTTP port, set
selfHostExternalHostto your public hostname, and keeppreferSelfHost: true. The explicit hostname skips public-IP auto-detection, but RSPM still attempts the Layer 3 probe. If the probe service itself is unreachable, RSPM keeps self-hosting instead of treating that communication failure as proof that your URL is unreachable.
I want to self-host the merged pack through my own web server
The code-supported setup is:
- Set
autoHost: false. - Set
resourcePackReroutingif you want ResourcePackManager to write an extra copy into an existing folder. - Host
ResourcePackManager_RSP.zipyourself.
resourcePackRerouting is resolved relative to the plugins directory, and the target folder must already exist.
If instead you want to use RSPM's built-in self-host HTTP server (different thing — same JVM as the plugin), see Self-hosting.
I need to inspect what remote data is stored for this server
Use:
/rspm data_compliance_request
If there is an active remote hosting session, ResourcePackManager downloads the response into:
plugins/ResourcePackManager/data_compliance/data.zip
RSPM also writes ReadMe.md in the same data_compliance folder.
If there is no remote session (e.g. you're using self-host), the command reports that there is no remote data to request.
Bedrock pack is not being generated
bedrockConversionEnabled defaults to true, so it should run automatically. Run /rspm status first — the Bedrock Pack section will tell you why the pack isn't on disk:
- "No Bedrock target detected" — no local Geyser-Spigot, no local Floodgate, and not in network mode. Conversion is intentionally skipped. Install Floodgate (for proxy setups) or Geyser-Spigot (for standalone setups) and
/rspm reload. - "Network mode is active so this backend SHOULD produce a Bedrock pack. The file is missing" — usually the first mix cycle hasn't completed yet (wait ~30s after boot), or conversion found neither convertible item mappings nor allowed entity bundles, or conversion threw. Search the console for
[BedrockConverter]warnings or forGeneric scanner: discovered 0 items definition files.
If Geyser auto-detection fails:
- Set
bedrockGeyserFolderinconfig.ymlto the path of your Geyser data folder (e.g.Geyser-Spigot). - Absolute paths work. A relative path is tried from the server working directory first, then relative to the
pluginsdirectory.
The converter auto-detects Geyser in plugins/Geyser-Spigot/, any plugins/Geyser-*/ variant, or config/Geyser-*/ for Fabric/NeoForge setups.
For per-item / per-bone log output, set bedrockConverterDebug: true and reload.
Bedrock: live provider skipped because a legacy pack exists
If the console reports Legacy RSPM Bedrock pack detected, Geyser already scanned an old ResourcePackManager_Bedrock.zip from its pack directory during boot. Deleting that file while the process is running would leave Geyser holding an in-memory codec for a path that no longer exists, so RSPM deliberately skips its live pack provider for that boot.
Fully stop the server, delete only the exact legacy file path printed by RSPM, then start the server again. Do not use /reload for this migration. The current pack remains in plugins/ResourcePackManager/output/ and is served per session; it does not belong in Geyser's packs/ directory.
Bedrock players see held items in the wrong position
This is a tuning issue, not a conversion bug. Open plugins/ResourcePackManager/bedrock_display_offsets.yml, adjust the relevant axis, run /rspm reload, and reconnect the Bedrock test client so the next join receives the rebuilt pack. First-person and third-person are independent — tuning one does not affect the other. See Bedrock conversion for the full list of knobs and what each one controls.
Custom armor textures are missing on Bedrock players
Custom armor renders on Bedrock by combining the vanilla armor geometry with the Java texture as a visible layer. For this to work, the source plugin's pack must define an equipment file under assets/<namespace>/equipment/<material>.json alongside the items definition. If the conversion log shows the item but no armor texture appears in-game, verify that file exists in the merged pack.
Proxy: a backend says it has no network key
On the backend, /rspm status shows Network key source: not set — the proxy sends one when a player next connects here, and the console repeats "This backend is behind a proxy but has no network key yet".
A missing plugins/floodgate/key.pem is not the cause — that file is optional now. The proxy owns the key: it loads its own network-key file, or seeds once from Floodgate's key.pem if present, or mints a fresh key, and then pushes it to each backend when a player connects there.
Check, in order:
- Has a player connected to that backend since the proxy started? The grant rides on a player connection.
- Is
ResourcePackManager.jaractually on the proxy? The backend stages a copy of its own jar for you atplugins/ResourcePackManager/proxy-extension/ResourcePackManager.jarand prints that path — copy it to the proxy'splugins/and restart the proxy. - On Velocity with modern forwarding, does the backend's forwarding secret match the proxy's? A modern-forwarding backend deliberately rejects an unsigned or wrongly-signed grant; its log states which. Fix the secret on both sides and the next player connect retries by itself.
- Compare the
Network key fingerprintlines from/rspm statuson both sides. Identical fingerprints mean the link is good; the key itself is never printed.
See Proxy networks for the full sequence.
Proxy: "Could not save the network key"
The proxy resolved a key but could not write it to its network-key file. This boot still works. The next restart mints a different key, and every backend already provisioned keeps the old one and refuses the new one — the whole network silently unlinks.
Fix the filesystem permissions on the proxy plugin's data folder before restarting.
Proxy: "no merged pack" after several poll cycles
After ~20 seconds of empty poll cycles (4 cycles × 5 s default interval) on the proxy, RSPM logs a one-shot diagnostic banner listing every backend it polled, the HTTP URL it tried, and the outcome (200 / 304 / 404 / CONNECT_FAILED / etc.). The banner explains the most common fixes:
CONNECT_FAILEDon every backend → the proxy can't reach the backend's HTTP port. Check that the address invelocity.toml/config.ymlis one the proxy can actually reach (not e.g. a Docker-internal name that doesn't resolve from the proxy's network), and that the backend's announced HTTP port is open between proxy and backend. The banner prints the exact URL it tried; before a backend has announced its port the proxy falls back tomcPort + network-http-offset-v2, so an earlyCONNECT_FAILEDcan also mean that fallback port isn't reachable yet.NOT_FOUND_404on every backend → backends are up but not producing a Bedrock pack. Run/rspm statuson each backend; the Bedrock Pack diagnostic block will tell you why.
The banner fires once per stuck period and an "NetworkSync: recovered" line is logged when at least one backend starts returning content again. See Proxy networks for more.
Proxy: Bedrock players see no models on first proxy boot
Geyser registers its custom-item table at proxy startup only. If the proxy started before any backend produced a Bedrock pack, Geyser is running with an empty mappings table and stays that way for the rest of the session.
The fix is to restart the proxy once the proxy has logged Merged Bedrock pack published at .... RSPM pre-deploys the previous run's mappings on proxy boot so this only ever bites on a brand-new install — subsequent boots have something ready before Geyser scans.
Backend: "Backend HTTP server failed to bind on port X"
In network mode, the backend exposes its Bedrock outputs through a small HTTP server. If the port is in use or unavailable, you'll see a multi-line [ERROR] block in the console. Fixes:
- Set
selfHostPortto a different positive value inconfig.yml. - Or change
networkHttpOffset-v2to push the auto-derived port away from the collision (e.g. RCON onmcPort + 1? set it to 2 or 3). You do not need to update the proxy to match: once the backend binds successfully it announces its actual HTTP port to the proxy automatically, so the proxy's ownnetwork-http-offset-v2only matters as a pre-announcement guess.
While the backend HTTP server is down, this backend's Bedrock pack won't reach the proxy via direct fetch. The magmaguy.com relay fallback still works (the backend pushes its files to the relay and the proxy fetches them through there).
Cleaning up an outdated v1 config
Operators upgrading from RSPM v1 may have a dead networkHttpOffset (no -v2) key in their config.yml. RSPM v2 intentionally does not read the old key — you get the v2 default (1) written to config on next boot automatically. The dead v1 key sits in your config as a harmless artifact until you clean it up by hand.