Skip to content

Explain frozen-registry writes from Fabric mods - #2321

Closed
1499501762 wants to merge 1 commit into
Sinytra:26.1.xfrom
1499501762:connector-frozen-registry-diagnostic
Closed

1499501762 wants to merge 1 commit into
Sinytra:26.1.xfrom
1499501762:connector-frozen-registry-diagnostic

Conversation

@1499501762

Copy link
Copy Markdown

What this does

Adds a log line when a Fabric mod writes into a registry that NeoForge already froze, naming the mod, the key and the registry, and pointing at the supported alternatives. Nothing else changes - the exception is still thrown exactly as before, no write is relaxed or deferred.

Why

fabric-registry-sync redirects BuiltInRegistries.bootStrap() inside Bootstrap to createContents() and calls the real bootstrap again from Main, so the freeze happens after mod initializers have run. NeoForge keeps the vanilla order and freezes during bootstrap, i.e. before mods are constructed. A Fabric mod that registers from a BuiltInRegistries.freeze() hook therefore fails with:

java.lang.IllegalStateException: Registry is already frozen
    (trying to add key ResourceKey[minecraft:root / create:arm_interaction_point_type])

and all the user sees is that line plus a stack in which Connector does not appear at all - which makes it look like an injection problem at first.

Concrete trail, from Create Fly: its own onInitialize hook skips Create.register() whenever fabric-api is present, so on Connector the @At("TAIL") hook becomes the first touch of the registry class and the write lands on an already frozen registry. The same jar starts fine on Fabric (Done (0.223s)!), so this is an ordering difference rather than a broken mixin.

Verification

  • Create Fly on a NeoForge 26.1.2.112 server with this change: one line, correctly attributed - The Fabric mod 'create' is registering 'create:arm_interaction_point_type' into 'minecraft:root' after that registry was frozen. - and Mixin apply for mod failures stay at 0.
  • Fabric Carpet control run: no such line (the normal path stays silent), server reaches Done, no injection errors.

Caveat: I could not run the Gradle build in my environment (forgified-fabric-loader:2.5.85+0.19.3+26.1.2 is not resolvable outside the local publish chain), so I verified by compiling this mixin against the current connector.jar and injecting it plus the mixins.json entry into a copy of that jar. The source change itself is these two files, and the injector resolves against MappedRegistry.validateWrite(ResourceKey).

Not part of this PR

This does not make Create Fly start. With the registry ordering worked around it then fails on A non-vanilla reload listener ... was added via mixin before the AddReloadListenerEvent. That is the reason this PR only improves the diagnostic instead of relaxing MappedRegistry.validateWrite globally - the shim would carry a large blast radius for no user-visible gain here.

fabric-registry-sync redirects BuiltInRegistries.bootStrap() inside Bootstrap to
createContents() and calls the real bootstrap again from Main, so the registry freeze only
happens after mod initializers have run. NeoForge keeps the vanilla order and freezes during
bootstrap, i.e. before mods are constructed.

A Fabric mod that registers from a BuiltInRegistries.freeze() hook, or from a late mod-init
path, therefore fails with "Registry is already frozen" and gets a stack trace that says
nothing about why it works on Fabric.

This only adds a log line naming the mod, the key and the registry, plus the supported
alternatives. Nothing is cancelled, deferred or relaxed - the exception is still thrown
exactly as before.

Attribution uses the namespace of the key being registered, which is the mod id for
essentially every Fabric mod. Resolving the calling class instead would need a class load or a
stack walk, and an entry point can register on behalf of another mod anyway.
@1499501762
1499501762 marked this pull request as draft October 1, 2026 14:31
@Lolothepro

Copy link
Copy Markdown

but... why?

@Su5eD

Su5eD commented Oct 2, 2026

Copy link
Copy Markdown
Member

This is not necessary, and also the whole PR looks AI generated.

Caveat: I could not run the Gradle build in my environment (forgified-fabric-loader:2.5.85+0.19.3+26.1.2 is not resolvable outside the local publish chain), so I verified by compiling this mixin against the current connector.jar and injecting it plus the mixins.json entry into a copy of that jar. The source change itself is these two files, and the injector resolves against MappedRegistry.validateWrite(ResourceKey).

:D

@Su5eD Su5eD closed this Oct 2, 2026
@github-project-automation github-project-automation Bot moved this from 🆕 New to ✅ Done in Connector Triage Oct 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: ✅ Done

Development

Successfully merging this pull request may close these issues.

3 participants