Identify which stage is failing
A Paper server resource pack crosses several separate boundaries before a player sees one changed texture. The pack must be a valid ZIP for that client's Minecraft version, an unauthenticated web request must return the intended bytes, server.properties must describe those exact bytes, and the player must accept and load them. Treating all four as one problem leads to random cache clearing and property changes that hide the useful evidence.
Begin with one clean test account and write down the exact client version, server version, pack filename, public URL, SHA-1 value and resource-pack UUID. Record what the player observes: no prompt, a rejected download, a successful download followed by a load error, or a pack that loads but renders the wrong assets. Capture the corresponding server and client log time. Each result points to a different stage.
Keep the first repair optional by leaving require-resource-pack=false. Paper's current server-properties reference says that enabling this setting kicks a player who does not have the offered pack. Requiring an unverified pack can lock every ordinary player out at once. Make the optional flow pass from an outside network, then decide whether the community truly needs enforcement.
- No prompt: inspect the active properties and the server restart first.
- Download fails: test the public URL, redirects, permissions and returned file.
- Download succeeds but loading fails: inspect ZIP structure and version compatibility.
- Pack loads but looks old: compare the served bytes, SHA-1 and release UUID.
Validate the ZIP before uploading it
Open the final archive locally. pack.mcmeta must sit at the root of the ZIP beside the assets directory, not inside an extra folder such as my-pack-v3. A common mistake is selecting the containing folder when compressing, which creates my-pack-v3/pack.mcmeta and gives the client no root manifest to read. Remove editor files and source artwork that the game does not need so the download stays small and predictable.
Test that exact ZIP as a normal client resource pack on the same Minecraft release that players will use. Do not rely on a pack that worked several releases ago: resource-pack metadata and asset behavior change with the game. Read the current release notes or pack documentation, update pack.mcmeta for the supported version range, and check the client log for missing metadata, invalid JSON, absent assets and namespace or path errors.
Use lowercase asset paths and verify letter case on the final archive. A pack assembled on a case-insensitive desktop can appear correct while two differently cased paths behave differently after upload or extraction on Linux. Keep one versioned source directory and produce one immutable ZIP from it. The file you test locally must be the file you hash and publish; rebuilding after hashing creates a different release even when the filename stays the same.
- Confirm pack.mcmeta and assets are at the ZIP root.
- Open pack.mcmeta as JSON and verify its declared compatibility deliberately.
- Test the final archive in the target Java client before server delivery.
- Remove nested wrapper folders, duplicate manifests and unnecessary source files.
Publish one direct immutable download
Upload the ZIP to an HTTPS file endpoint that players can reach without signing in, accepting cookies or opening a download page. Use a versioned object name such as server-pack-2026-09-10.zip instead of replacing latest.zip in place. An immutable URL makes rollback and diagnosis possible: everyone testing one release should receive the same bytes, regardless of edge cache or browser history.
Test from a device or network that is not authenticated to the storage provider. A normal GET request should return the ZIP rather than HTML for a login, consent screen, expired-share warning or missing-file page. Follow redirects and inspect the final status, content length and content type. Then download the file to a new directory and open it. A URL ending in .zip proves nothing when the response body is actually a branded error page.
Keep the pack endpoint public but the storage account private. Players need read access to one object, not write access to the bucket, deployment repository or hosting panel. Do not embed tokens with administrative permissions in server.properties. If a signed URL expires, the server will continue offering a dead address; choose a stable public-read object or a deliberately managed delivery endpoint and monitor it after each release.
Hash the exact bytes players receive
Paper exposes resource-pack-sha1 as the hash used to verify the pack and recommends setting it so players download the intended file. Calculate SHA-1 after the final ZIP is complete. On Linux, sha1sum server-pack-2026-09-10.zip prints the required hexadecimal value. In PowerShell, run (Get-FileHash .\server-pack-2026-09-10.zip -Algorithm SHA1).Hash.ToLower(). Paste only the 40 hexadecimal characters, without a filename, prefix or spaces.
SHA-1 is required here because it is the protocol field Paper exposes, not because SHA-1 is a modern choice for signing software. Microsoft's Get-FileHash documentation notes that SHA-1 is no longer considered secure against attack; in this workflow it identifies the exact bytes the client should receive. Protect the publishing account and source separately, and use stronger checksums in your release records when available.
Download the public URL into a different file and hash that response too. Its SHA-1 must match the local release. A mismatch proves that the CDN, object key or upload does not serve the tested file. Do not solve it by pasting the unexpected public hash into Paper until you have opened and identified those bytes. Correct the upload, use a new versioned URL, calculate again and preserve both the ZIP and release note.
- Hash only after the final archive is built.
- Compare the local ZIP with a fresh unauthenticated download.
- Store the URL, SHA-1, stronger checksum and release date together.
- Publish a new object rather than mutating a cached release in place.
Configure Paper as one matched release
Stop Paper cleanly and back up server.properties before editing it. The controlled maintenance approach in /blog/update-paper-minecraft-server-safely applies here: change offline files, preserve the previous known-good values and perform a full restart. A reload command is not a substitute for proving that the actual service read the intended properties file. Similar directories and panel templates are common, so confirm the working directory from the startup environment.
Set resource-pack to the direct HTTPS URL and resource-pack-sha1 to the matching 40-character value. Set resource-pack-id to a new UUID for this pack release; keep the same UUID only while the release identity is unchanged. resource-pack-prompt controls the message shown with the client prompt. Start with require-resource-pack=false until the complete acceptance pass succeeds. Each setting has one job, which makes the next failure easier to locate.
A practical optional example is resource-pack=https://files.example.com/server-pack-2026-09-10.zip, resource-pack-sha1=<40-character-hash>, resource-pack-id=<release-uuid>, resource-pack-prompt={"text":"Download the server resource pack for custom visuals."}, and require-resource-pack=false. Put each property on its own line and replace every placeholder. Avoid smart quotes copied from formatted documents, then restart and inspect the beginning of the log for property parsing or startup errors.
- resource-pack: the stable direct HTTPS download URL.
- resource-pack-sha1: the SHA-1 of that exact public ZIP.
- resource-pack-id: the UUID identifying this pack release.
- resource-pack-prompt: a short honest message shown to players.
- require-resource-pack: false during testing; enable only after acceptance.
Test the player journey outside the server
Join with a non-operator account that has never accepted this release. Check the multiplayer server entry and ensure its Server Resource Packs preference is not Disabled. The expected optional flow is a clear prompt, one successful download, pack application and a normal join. Reconnect and restart the client to verify that the result persists. Test at least one other operating system when the community uses several platforms.
Inspect the client log as well as Paper's console. If no prompt appears after a verified restart, confirm the player reached the intended backend and that a proxy or plugin is not providing its own pack. If the download fails, fetch the same URL outside Minecraft and compare the status and SHA-1. If loading fails after a correct download, return to pack.mcmeta, archive root, target version and the first relevant client-side error.
Do not diagnose by deleting every cached pack first. A clean test profile can separate local state without destroying useful evidence. When cache state is genuinely suspect, preserve the failing log, close the client, remove only the relevant downloaded server-pack entry according to that client's current layout, and repeat once. If a new version is being tested, prefer a new URL, hash and UUID so the release is unambiguous.
Deploy, monitor and roll back safely
Once optional tests pass, decide whether refusal should prevent joining. require-resource-pack=true is appropriate only when the pack is essential to understand the world or interface and the download endpoint is reliable. Tell players what the pack changes and how large it is before enforcement. Keep an administrator account with a tested recovery path so a broken file host cannot turn a visual update into an unexplained server outage.
Monitor the pack URL, response size and hash after deployment. Test a new player join after CDN, DNS or storage changes, not only after editing the pack. Keep the previous ZIP, URL, UUID, hash and properties values. If failures rise, restore that complete known-good set or temporarily make the pack optional; changing only the URL while leaving an unrelated hash creates another failure state.
Treat every pack update as a small release: build, local test, publish, re-download, hash, configure, restart and accept from outside. More focused server administration guides live at /blog. If reliable file delivery, backups or support exceed the current setup, compare the documented options at /pricing after the pack itself passes validation. Hosting cannot repair a malformed ZIP, but a repeatable release process prevents most server-pack incidents.
Frequently asked questions
Quick answers
Why is my Minecraft server resource pack not downloading?
Test the URL without being signed in. It must return the intended ZIP, not a login page, expired link or HTML error. Then compare the fresh download's SHA-1 with resource-pack-sha1.
Where does a Paper server resource pack go?
Paper does not need the ZIP inside its server directory. Host the final ZIP at a stable public HTTPS URL and put that address in the resource-pack property.
How do I calculate resource-pack-sha1?
Run sha1sum on Linux or Get-FileHash with -Algorithm SHA1 in PowerShell against the final ZIP. Use only the resulting 40 hexadecimal characters.
Should require-resource-pack be true?
Keep it false while testing. Set it true only after outside clients can download and load the exact release reliably, because players who refuse or lack a required pack are kicked.
Why does Minecraft download the pack but fail to load it?
Check that pack.mcmeta and assets are at the ZIP root, the metadata is valid JSON, the pack supports the client's game version, and the client log does not report missing or invalid assets.
