Menu

Guidefor modders4 min read

Porting a mod to a new Minecraft version

Mappings, the compile errors that come first, the behaviour changes that come later, and the order that makes a port take days instead of weeks.

Why a port is work at all

Through 1.21.11, Minecraft shipped obfuscated: class and method names in the released jar were meaningless short strings that changed every build, because nothing was meant to depend on them. Mojang removed obfuscation starting with 26.1, the first calendar-versioned release, so a build from that point on ships with its real names intact.

That changes what a mapping set is for going forward, but not the underlying problem this guide is about. Mappings still exist to map obfuscated builds back to readable names, a mapping set is still specific to one Minecraft version, and every release before 26.1 still needs them. If you are porting across the 1.21.11-to-26.1 boundary, or supporting a version on either side of it, you are still dealing with two different naming systems either way.

Even with obfuscation gone, a port is still never just a version bump: names still get renamed as the game's own code is refactored, methods still change shape, and some things are simply removed. Real names instead of obfuscated ones make the diff easier to read, not the diff itself smaller.

Do it in this order

The mistake that makes ports drag on is fixing errors as they appear in the file you happen to have open. Work in layers instead.

1. Update the toolchain, before touching your code

Bump the Minecraft version, the mappings, the loader version and the API version in your build file. Nothing else. Then compile and look at the wall of errors.

That wall is your actual work list. Reading it before changing anything tells you whether this is a two-hour port or a two-week one, which is worth knowing before you start.

2. Fix the renames

Most of the errors will be one thing renamed. These are mechanical: find the new name, apply it everywhere.

Two things make this much faster:

  • A mapping diff between the two versions, which tells you what became what, rather than guessing from similar names.
  • Fixing all instances of one rename at once rather than file by file. The same method usually appears in a dozen places.

3. Fix the structural changes

What is left is real work: a method that changed signature, a class that split, a system that was replaced.

Here the loader's migration notes are worth reading properly, and so is the decompiled source. When a method is gone with no obvious replacement, search the decompiled game for its old behaviour and see what performs it now.

4. Fix the registration order

Both loaders move registration timings between versions more often than they change the registration API. Code that registered at the right moment can now be too early or too late.

These fail at runtime rather than at compile time and often produce confusing errors about something being absent, so they are worth checking deliberately rather than waiting to trip over them.

5. Then test behaviour

Everything compiles and loads. Now find the things that changed quietly: an event firing at a different point, a value that can now be null, an ordering that flipped.

Nothing errors here. Your mod is just wrong. This is the layer that produces bug reports a week after release, and the only defence is exercising your mod's actual features rather than confirming the game starts.

Start at the pre-release

The release cycle gives you a schedule if you use it:

  • Snapshots. Things are still moving. Porting now means redoing it.
  • Pre-releases. Feature complete, API mostly settled. This is when to start.
  • Release candidates. If your port works here, it works on release day, because the release is usually this exact code.

Being ready on release day is worth more to your users than any feature you could have added that month, particularly for library mods, where everything downstream is waiting on you.

Supporting two versions at once

Two shapes, and picking wrong costs months:

Shared module plus per-version sources. One project, common code in one place, small version-specific source sets. Right when the differences are small.

Separate branches. Right when they are not. Once the versions diverge enough, keeping one codebase that satisfies both costs more than maintaining two, and produces code neither of you enjoys reading.

Be honest about which you are in. A shared module full of version checks is a branch that has not admitted it yet.

Publishing the port

  • Declare the exact Minecraft versions in your release metadata, not just in the description. That metadata is what catalogues read, including the mod catalogue here, which filters on those exact declarations. Writing "1.21" when you mean every 1.21.x, or the reverse, is what makes users and catalogues disagree.
  • Declare your loader. A build for one never runs on another. See why mods are loader specific.
  • Bump your dependency ranges to what you actually tested against.
  • Write a real changelog if behaviour changed. A port that silently alters a mechanic people built around is worse than one that says so.

Frequently asked

Why does the game's code have different names every version?

Through 1.21.11, Mojang shipped obfuscated builds, so internal names were meaningless strings that changed every build, and mappings mapped them back to readable names for a specific version. Mojang removed obfuscation starting with 26.1, so builds from that point ship with real names, but every earlier version still needs its own mapping set, and names still change across releases as the code itself is refactored.

Can I support two Minecraft versions from one branch?

For small differences, yes, with a shared module and per-version source sets. Across a large change the branches diverge enough that maintaining both costs more than maintaining two.

When should I start porting?

At the pre-release stage. The API is settled enough by then to be worth your time, and starting at the snapshot stage means redoing work as things move.

How do I find what replaced a removed method?

The mapping diff between versions, and the loader's own migration notes. Failing both, search the decompiled source for the old behaviour and see what calls it now.

Space NodePartner

Host Minecraft servers

Deploy a Minecraft server in under a minute. Installed, tuned and ready to play.

  • Instant deployment
  • Automatic updates
  • Ryzen CPUs
  • NVMe SSD
Deploy a serverFrom €0.90 per GB

Referenced on this site

Last reviewed 2026-07-27. Version data on this site updates automatically; this guide is reviewed by hand when the ecosystem changes.

Is this information wrong or missing something? .