Skip to main content
A plain stage0 jar of Essential Loader by default will dynamically load the latest version of Essential. However, it can also be configured to load any other mod or a specific branch (e.g., beta or staging instead of stable).

What is a Container Mod?

A container mod is an Essential-using dummy mod that’s just a stage0 with an embedded configuration file and no functionality of its own. It’s a thin container for the loader rather than the actual mod.

Thin Container Mods

A thin container mod contains:
  • Stage0 loader code
  • Configuration file pointing to a mod
  • No embedded mod jar
Always downloads the latest version from the update server.

Pinned Container Mods

A pinned container mod additionally embeds a specific version of the mod:
  • Works fully offline
  • Can enable auto-updates programmatically
  • Supports click-to-update functionality
When auto-updates are enabled, the container mod behaves like a regular thin container jar, ignoring the embedded version.

Update Modes

Auto-Update

Automatically downloads and installs the latest version on each game boot. Pinned versions are ignored.

Click-to-Update

Notifies the user in-game when an update is available. User decides whether to upgrade or stay on the current version.

Pinned

Uses the embedded version. Updates only when the user explicitly chooses or the container mod is updated.

One-Time Download

Downloads the latest version once if not already present, then uses that cached version.

Configuration

Container Mod Configuration

The container mod is configured via an essential-loader.properties file at the root of the jar:
# The publisher and mod slug as set in the Essential Mods Panel
publisherSlug=essential
modSlug=examplemod

# Optionally, the publisher and mod ID as displayed in the Essential Mods Panel
publisherId=26d49e5b60ecf53d6b26c76a
modId=60ecf53d6b26c76a26d49e5b

# A display name for use in UI and log messages
displayName=ExampleMod

# Optional, the branch from which updates should be pulled, defaults to `stable`
branch=stable
  • publisherSlug: Your publisher username from Essential’s Mods Panel
  • modSlug: Your mod’s slug identifier from Essential’s Mods Panel
  • publisherId: (Optional) Your publisher ID for additional validation
  • modId: (Optional) Your mod ID for additional validation
  • displayName: Human-readable name shown to users
  • branch: Which update channel to follow (stable, beta, staging, etc.)

Pinning a Mod

To create a pinned container mod, embed the mod jar and add these properties:
# The path to the embedded mod jar inside the container jar. Should be unique to 
# this mod+version so it cannot clash with other mods or versions of the same mod.
# Must include the leading slash, otherwise it will be read as a regular URL, 
# not a path inside the jar.
pinnedFile=/path-to-embedded.jar

# MD5 checksum of the above file
pinnedFileMd5=d41d8cd98f00b204e9800998ecf8427e

# Optional, the version as named in the Essential Mods Panel of the embedded jar.
# Required if click-to-update is used.
# May be required by your mod if it wants to know its own version.
# Also required for diff-updates, otherwise the full jar will be downloaded on the 
# first update.
pinnedFileVersion=1.2.0

# Optional, the ID of the version of the embedded jar.
# If provided, may be used instead of the human-readable version in certain places. 
# Currently unused.
pinnedFileVersionId=6b26c76a26d49e5b60ecf53d
The pinnedFile path must include the leading slash (/). Without it, the path will be read as a regular URL, not a path inside the jar.
The MD5 checksum verifies the integrity of the embedded jar file. While MD5 is cryptographically weak, it’s perfectly suitable for detecting file corruption or accidental modifications.

Runtime Configuration

Container mods can be further configured programmatically (e.g., via an in-game user interface) to enable/disable auto-updates or switch to a specific version/branch. Configuration file location:
.minecraft/essential/mods/$pub_$mod/essential-loader.properties
Where:
  • $pub is the mod’s publisherSlug
  • $mod is the mod’s modSlug
If publisherSlug and modSlug are identical, the folder name is shortened to just $mod.For legacy reasons, Essential itself uses .minecraft/essential/essential-loader.properties.
Available properties:
# Whether update checks are enabled.
# When set to `true`:
#   The mod is updated to the latest version at `branch` on each game boot. 
#   Pinned versions are ignored.
# When set to `false`:
#   If a version is already downloaded, loads that version; otherwise downloads 
#   the latest version once or uses the latest pinned version if there is one.
# When set to `with-prompt`:
#   Checks for updates and sets the `pendingUpdateVersion` property if one is found.
#   The mod is then expected to show an in-game update prompt and write to the 
#   `pendingUpdateResolution` property either `true` if the user accepted the 
#   upgrade or `false` if they want to ignore it.
#   If the mod fails to write to the property, the loader will show its own prompt 
#   to allow the user to update even if the current mod version is bricked.
# Defaults to `true` unless there is a pinned jar present in which case it 
# defaults to `with-prompt`.
autoUpdate=true

# Specifies the branch to follow if autoUpdate is enabled.
branch=beta

# Set by the loader when there is an update available.
# This value **MUST NOT BE MODIFIED** by the mod.
# Instead `pendingUpdateResolution` should be set.
pendingUpdateVersion=1.2.0.13

# Should be set by the mod when it finds the `pendingUpdateVersion` property to be set.
# If the mod fails to write the property, the loader will show its own prompt to 
# allow the user to update even if the current mod version is bricked.
# Should be set to `true` to accept and download the update.
# Should be set to `false` to ignore this specific update.
pendingUpdateResolution=true

# INTERNAL USE ONLY
# Stores the last version to which the mod has accepted upgrading.
# Prevents downgrading when the container mod is upgraded (e.g. by a modpack author) 
# to a version that's older than this version:
# If a pinned jar is found that's older than this version, then that jar is ignored.
# If however a pinned jar is found that's newer than or equal to this version, then 
# that jar will be used and this property will be un-set to allow the user to 
# downgrade the mod by downgrading the container mod.
overridePinnedVersion=1.2.0.12

Update Workflow

Auto-Update Flow

Click-to-Update Flow

If the mod fails to write to the pendingUpdateResolution property, the loader will show its own prompt. This ensures users can still update even if the current mod version is broken or bricked.

Pinning Stage2

Stage2 can also be pinned, but with some limitations.
Stage2 pinning is only supported on Fabric and ModLauncher. On LaunchWrapper, the stage2 jar is already included in the stage1 jar and cannot be updated independently.

Configuration

Instead of an essential-loader.properties file at the root of the container mod, place the file at:
gg/essential/loader/stage1/stage2.properties
Required properties:
pinnedFile=/path/to/stage2.jar
pinnedFileMd5=abc123def456...
pinnedFileVersion=2.1.0
All three properties are required for stage2 pinning. Only pinnedFile, pinnedFileMd5, and pinnedFileVersion are supported.

Runtime Configuration

The external configuration file for stage2 is at:
.minecraft/essential/loader/stage1/$variant/config.properties
It provides:
  • autoUpdate
  • branch
  • pendingUpdateVersion
  • pendingUpdateResolution
With identical semantic meaning to the per-mod config files.
TODO: This needs more work before third-party usage!Stage2 is shared between all mods. We need a way to enable auto-updates only if one of the mods doesn’t have it pinned. Currently, a single mod can pin it for all, which is problematic with old loaders around.

Best Practices

For Mod Developers

  • Use pinned containers for stable releases
  • Enable click-to-update by default
  • Provide clear update prompts to users
  • Test offline functionality with pinned versions

For Modpack Authors

  • Pin versions for stability
  • Disable auto-updates in production packs
  • Document the update process for users
  • Test container mod compatibility

For Advanced Users

  • Use auto-update for bleeding-edge features
  • Switch branches for beta testing
  • Keep backups when experimenting
  • Understand the configuration hierarchy

For Distribution

  • Always include MD5 checksums
  • Use unique paths for embedded jars
  • Document the pinned version clearly
  • Provide migration guides for updates

Use Cases

Scenario: You’re distributing a modpack and want stable, tested versions.Solution: Use pinned container mods with auto-updates disabled.
pinnedFile=/mods/yourmod-1.5.0.jar
pinnedFileMd5=abc123...
pinnedFileVersion=1.5.0
Runtime config:
autoUpdate=false
Users get the exact version you tested, with no surprise updates.

Troubleshooting

Check the runtime configuration file at .minecraft/essential/mods/$pub_$mod/essential-loader.properties. It may have overridePinnedVersion set, causing the pinned version to be ignored.Solution: Delete the runtime config file or remove the overridePinnedVersion property.
Verify:
  • autoUpdate=true in runtime config
  • Internet connection is available
  • Publisher and mod slugs are correct
  • The mod exists on Essential’s API
Check logs for detailed error messages.
The embedded jar has been corrupted or modified.Solution: Re-build the container mod with the correct jar file and updated MD5 checksum.Generate MD5: md5sum yourmod.jar (Linux/Mac) or CertUtil -hashfile yourmod.jar MD5 (Windows)
Ensure:
  • autoUpdate=with-prompt in runtime config
  • pinnedFileVersion is set in the container mod config
  • The mod properly implements update prompt handling
If the mod doesn’t handle it, the loader should show a fallback prompt.

Build docs developers (and LLMs) love