Bundle_en.properties crashes Dataverse on startup
Nobody has claimed this yet.
- Dominant language
- Java
- Stars
- 1.1k
- Forks
- 564
- Avg merge
- 2d 2h
- Merged PRs (30d)
- 29
Description
What steps does it take to reproduce the issue?
- When does this issue occur?
When dataverse.lang.directory is configured and a Bundle_en.properties file exists in that directory (even an empty file), Dataverse fails to start after a restart or redeploy.
- Which page(s) does it occurs on?
Not page-specific; Dataverse fails during application deployment/startup. No pages are reachable.
- What happens?
- Deploy Dataverse 6.9 on Payara 6.2025.10 - verify it starts normally.
- Set the JVM option:
asadmin create-jvm-options -- "-Ddataverse.lang.directory=/usr/local/payara6/glassfish/domains/domain1/lang" - Create the directory and an override file (content does not matter — even an empty file triggers the bug):
mkdir -p /usr/local/payara6/glassfish/domains/domain1/lang touch /usr/local/payara6/glassfish/domains/domain1/lang/Bundle_en.properties chown -R dataverse:dataverse /usr/local/payara6/glassfish/domains/domain1/lang - Restart Payara:
systemctl restart payara - Dataverse fails to start with
NullPointerExceptioninPasswordValidatorServiceBean.<init>. The version API (/api/info/version) returns a Payara error page instead of JSON. Removing the file and restarting immediately resolves it.
- To whom does it occur (all users, curators, superusers)?
All users — the application does not start at all.
- What did you expect to happen?
Dataverse should start normally and use the keys in Bundle_en.properties as overrides for the English locale, as documented in the Installation Guide. This is the recommended upgrade-safe mechanism for text customizations.
Which version of Dataverse are you using?
- Dataverse: 6.9 (build 2027-e2021d3)
- Payara: 6.2025.10 (build 42)
- Java: OpenJDK 17.0.19 (Red Hat)
- OS: RHEL 8 (Rocky Linux 8)
Dataverse 6.10 likely affected as well (same code pattern present in the v6.10 source for GoodStrengthRule.java).
Any related open or closed issues to this bug report?
Not aware of any existing issues for this specific failure.
Screenshots:
Full stack trace from server.log:
[SEVERE] Exception while loading the app : EJB Container initialization error
java.lang.NullPointerException
at java.base/java.util.concurrent.ConcurrentHashMap.putVal(ConcurrentHashMap.java:1011)
at java.base/java.util.concurrent.ConcurrentHashMap.put(ConcurrentHashMap.java:1006)
at java.base/java.util.Properties.put(Properties.java:1301)
at java.base/java.util.Properties.setProperty(Properties.java:229)
at edu.harvard.iq.dataverse.validation.PasswordValidatorServiceBean.<init>(PasswordValidatorServiceBean.java:102)
at edu.harvard.iq.dataverse.validation.__EJB31_Generated__PasswordValidatorServiceBean__Intf____Bean__.<init>(Unknown Source)
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
...
at com.sun.ejb.containers.StatelessSessionContainer.initializeHome(StatelessSessionContainer.java:216)
at com.sun.ejb.containers.StatelessContainerFactory.createContainer(StatelessContainerFactory.java:63)
at org.glassfish.ejb.startup.EjbApplication.loadContainers(EjbApplication.java:225)
Root cause analysis:
GoodStrengthRule.java initializes static fields at class-load time by calling BundleUtil.getStringFromBundle():
static final String ERROR_CODE_GOODSTRENGTH = BundleUtil.getStringFromBundle("passwdVal.goodStrengthRule.errorCode");
static final String ERROR_MESSAGE_GOODSTRENGTH = BundleUtil.getStringFromBundle("passwdVal.goodStrengthRule.errorMsg");
When dataverse.lang.directory is set, BundleUtil attempts to load the ResourceBundle from the external directory during class loading. At this point during EJB container initialization, the resource bundle system is not fully available, so BundleUtil.getStringFromBundle() returns null. This null is then passed to Properties.setProperty() in PasswordValidatorServiceBean.<init> (line 102):
properties.setProperty(GoodStrengthRule.ERROR_CODE_GOODSTRENGTH, GoodStrengthRule.ERROR_MESSAGE_GOODSTRENGTH);
ConcurrentHashMap.put() (which backs Properties) does not allow null keys or values, hence the NPE.
Workaround:
Remove the JVM option to disable external bundle overrides entirely:
asadmin delete-jvm-options -- "-Ddataverse.lang.directory=/usr/local/payara6/glassfish/domains/domain1/lang"
This means text customizations cannot be externalized in an upgrade-safe way on 6.9.
Are you thinking about creating a pull request for this issue?
Happy to discuss, though the fix appears straightforward. The suggested (by my coding assistant) approach is to change GoodStrengthRule.java to lazy initialization so BundleUtil is not called during class loading:
class GoodStrengthRule extends LengthRule {
static String getErrorCode() {
return BundleUtil.getStringFromBundle("passwdVal.goodStrengthRule.errorCode");
}
static String getErrorMessage() {
return BundleUtil.getStringFromBundle("passwdVal.goodStrengthRule.errorMsg");
}
@Override
public RuleResult validate(PasswordData passwordData) {
final RuleResult result = super.validate(passwordData);
if (!result.isValid()) {
result.getDetails().clear();
result.getDetails().add(new RuleResultDetail(getErrorCode(), createRuleResultDetailParameters()));
}
return result;
}
}
And add a null guard in PasswordValidatorServiceBean:
public PasswordValidatorServiceBean() {
final Properties properties = PropertiesMessageResolver.getDefaultProperties();
String errorCode = GoodStrengthRule.getErrorCode();
String errorMessage = GoodStrengthRule.getErrorMessage();
if (errorCode != null && errorMessage != null) {
properties.setProperty(errorCode, errorMessage);
}
messageResolver = new PropertiesMessageResolver(properties);
}
This ensures BundleUtil is called at first validation use (when the application is fully initialized) rather than during class loading. I'm not a java developer and I have not tested this at all so I'm not sure how reasonable this suggestion is.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with GoodStrengthRule.java and PasswordValidatorServiceBean.java, then trace BundleUtil.getStringFromBundle() and the constructor path shown in the stack trace. Reproduce with dataverse.lang.directory and an external Bundle_en.properties file, and inspect existing validation tests before changing initialization. Done means Dataverse starts with the override file present and password validation still supplies the expected localized error details.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java
- Domain
- backend, internationalization
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 55/100