Summary
Eleven of the sixteen product modules override UltiToolsPlugin.reloadSelf(). Nine of those overrides never call super.reloadSelf(), so /ul reload for those modules logs "configuration reloaded" while reloading nothing. Two modules (UltiLogin, UltiWorlds) were fixed in Phase 13 of the 6.3.0 milestone after the defect was found independently in each — the same cause, twice. This issue tracks the remaining nine and proposes closing the class of defect in the framework rather than fixing it a tenth time.
Measured (2026-09-06, all sixteen module repositories at their current heads)
| Module |
Overrides reloadSelf() |
Calls super.reloadSelf() |
| UltiBackup |
yes |
no |
| UltiCleaner |
yes |
no |
| UltiEssentials |
yes |
no |
| UltiMail |
yes |
no |
| UltiRecipe |
yes |
no |
| UltiRemoteBag |
yes |
no |
| UltiSideBar |
yes |
no |
| UltiSocial |
yes |
no |
| UltiTrade |
yes |
no |
| UltiLogin |
yes |
yes (fixed, UltiKits/UltiLogin#18) |
| UltiWorlds |
yes |
yes (fixed, UltiKits/UltiWorlds#16) |
| UltiBot, UltiChat, UltiEconomy, UltiKits, UltiMenu |
no override |
inherits the framework behaviour |
Every one of the nine non-calling overrides has the same body shape — a single getLogger().info(i18n("<Module> 配置已重载!")) line.
What super.reloadSelf() does (abstracts/UltiToolsPlugin.java, current alpha): getConfigManager().reloadConfigs(this), then re-creates the language catalogue, then ConditionalRegistrationEvaluator.reportDrift(this). The method's own javadoc already states that an override which skips super "will not get this report" — the contract is documented, and nine modules break it.
Why this belongs in the framework, not in nine more module pull requests
The two fixes already landed are one line each (super.reloadSelf();) plus a test that fails when the line is removed. Repeating that nine more times leaves the defect class in place: the next module author who overrides reloadSelf() to add a log line reproduces it. This milestone's core value is that a declared surface must do what it declares; a hook whose contract depends on every override remembering one call does not.
Proposed direction (maintainer decision — two shapes, one breaking and one not)
- Template method (breaking, structural). Make the reload entry point the framework calls non-overridable, and expose a
protected void onReload() hook that modules override instead. Every existing override then fails to compile, which is the point — the defect cannot be written. Cost: a public-API change on UltiToolsPlugin (COMPATIBILITY.md entry; all eleven overriding modules need a one-line rename), so it belongs in its own phase, not appended to Phase 13.
- Runtime detection (non-breaking, interim). Have
super.reloadSelf() set a per-call sentinel and have the framework's reload dispatcher log a WARNING naming the module when an override returns without the sentinel set. Silent no-op becomes a loud no-op without changing any signature. Does not prevent the defect, only exposes it.
Option 1 is the root-cause fix; option 2 is what to ship if option 1 waits for a major release.
Module issues
UltiKits/UltiBackup, UltiKits/UltiCleaner, UltiKits/UltiEssentials, UltiKits/UltiMail, UltiKits/UltiRecipe, UltiKits/UltiRemoteBag, UltiKits/UltiSideBar, UltiKits/UltiSocial, UltiKits/UltiTrade — one issue each, linked back here (numbers listed in the first comment below once created).
Found by
Phase 13 of the 6.3.0 milestone, 2026-09-06: after UltiLogin#13 and UltiWorlds#10 were both traced to this cause, the remaining fourteen modules were measured with grep -rl 'void reloadSelf' src/main/java plus a per-method scan for super.reloadSelf. The maintainer decided on the same day to track the nine here rather than widen Phase 13, whose scope is the defects the ecosystem acceptance pass found.
Summary
Eleven of the sixteen product modules override
UltiToolsPlugin.reloadSelf(). Nine of those overrides never callsuper.reloadSelf(), so/ul reloadfor those modules logs "configuration reloaded" while reloading nothing. Two modules (UltiLogin, UltiWorlds) were fixed in Phase 13 of the 6.3.0 milestone after the defect was found independently in each — the same cause, twice. This issue tracks the remaining nine and proposes closing the class of defect in the framework rather than fixing it a tenth time.Measured (2026-09-06, all sixteen module repositories at their current heads)
reloadSelf()super.reloadSelf()Every one of the nine non-calling overrides has the same body shape — a single
getLogger().info(i18n("<Module> 配置已重载!"))line.What
super.reloadSelf()does (abstracts/UltiToolsPlugin.java, currentalpha):getConfigManager().reloadConfigs(this), then re-creates the language catalogue, thenConditionalRegistrationEvaluator.reportDrift(this). The method's own javadoc already states that an override which skipssuper"will not get this report" — the contract is documented, and nine modules break it.Why this belongs in the framework, not in nine more module pull requests
The two fixes already landed are one line each (
super.reloadSelf();) plus a test that fails when the line is removed. Repeating that nine more times leaves the defect class in place: the next module author who overridesreloadSelf()to add a log line reproduces it. This milestone's core value is that a declared surface must do what it declares; a hook whose contract depends on every override remembering one call does not.Proposed direction (maintainer decision — two shapes, one breaking and one not)
protected void onReload()hook that modules override instead. Every existing override then fails to compile, which is the point — the defect cannot be written. Cost: a public-API change onUltiToolsPlugin(COMPATIBILITY.md entry; all eleven overriding modules need a one-line rename), so it belongs in its own phase, not appended to Phase 13.super.reloadSelf()set a per-call sentinel and have the framework's reload dispatcher log aWARNINGnaming the module when an override returns without the sentinel set. Silent no-op becomes a loud no-op without changing any signature. Does not prevent the defect, only exposes it.Option 1 is the root-cause fix; option 2 is what to ship if option 1 waits for a major release.
Module issues
UltiKits/UltiBackup, UltiKits/UltiCleaner, UltiKits/UltiEssentials, UltiKits/UltiMail, UltiKits/UltiRecipe, UltiKits/UltiRemoteBag, UltiKits/UltiSideBar, UltiKits/UltiSocial, UltiKits/UltiTrade — one issue each, linked back here (numbers listed in the first comment below once created).
Found by
Phase 13 of the 6.3.0 milestone, 2026-09-06: after UltiLogin#13 and UltiWorlds#10 were both traced to this cause, the remaining fourteen modules were measured with
grep -rl 'void reloadSelf' src/main/javaplus a per-method scan forsuper.reloadSelf. The maintainer decided on the same day to track the nine here rather than widen Phase 13, whose scope is the defects the ecosystem acceptance pass found.