apache/hadoop · error · IOException
Can't store credential " + alias + " in " + this
Error message
Can't store credential " + alias + " in " + this
What it means
Thrown by innerSetCredential() when KeyStore.setKeyEntry() rejects the new SecretKeySpec(AES) entry with KeyStoreException. The keystore instance cannot protect/store this kind of key - classically because the store is effectively not a JCEKS store capable of holding secret keys, or its state was not properly initialized for writes.
Source
Thrown at hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/alias/AbstractJavaKeyStoreProvider.java:274
}
} catch (KeyStoreException e) {
throw new IOException("Problem removing " + name + " from " + this, e);
}
changed = true;
} finally {
writeLock.unlock();
}
}
CredentialEntry innerSetCredential(String alias, char[] material)
throws IOException {
writeLock.lock();
try {
keyStore.setKeyEntry(alias,
new SecretKeySpec(new String(material).getBytes(StandardCharsets.UTF_8),
getAlgorithm()), password, null);
} catch (KeyStoreException e) {
throw new IOException("Can't store credential " + alias + " in " + this,
e);
} finally {
writeLock.unlock();
}
changed = true;
return new CredentialEntry(alias, material);
}
@Override
public void flush() throws IOException {
writeLock.lock();
try {
if (!changed) {
LOG.debug("Keystore hasn't changed, returning.");
return;
}
LOG.debug("Writing out keystore.");
try (OutputStream out = getOutputStreamForKeystore()) {View on GitHub (pinned to 2add963021)
Solutions
- Let Hadoop create the store itself: run 'hadoop credential create <alias> -provider jceks://file/<path>' on a clean path so the file is born as JCEKS
- If the file came from keytool, re-create it with -storetype jceks, or export/import the secrets into a fresh Hadoop-managed store
- Check javax keystore.type/provider overrides in java.security and the JVM's provider list; remove FIPS restrictions or add a provider that supports JCEKS key protection
Example fix
# before keytool -genkeypair -keystore /etc/hadoop/creds.jceks # writes JKS-format store hadoop credential create s3.key -provider jceks://file/etc/hadoop/creds.jceks # fails: Can't store credential # after rm /etc/hadoop/creds.jceks hadoop credential create s3.key -provider jceks://file/etc/hadoop/creds.jceks # Hadoop creates a true JCEKS store
Defensive patterns
Strategy: validation
Validate before calling
// Pre-flight: the existing file must be a loadable JCEKS before writing entries
static boolean isHealthyJceks(Path file, char[] pw) throws Exception {
if (!file.toFile().exists() || file.toFile().length() == 0) return true; // will be created fresh
KeyStore ks = KeyStore.getInstance("jceks");
try (InputStream in = Files.newInputStream(file)) {
ks.load(in, pw);
return true;
} catch (Exception e) {
return false;
}
} Try / catch
try {
provider.createCredentialEntry(alias, material);
provider.flush();
} catch (IOException ex) {
if (ex.getCause() instanceof java.security.KeyStoreException) {
// store type cannot hold secret keys or is uninitialized:
// recreate the file via hadoop credential on a clean path, then retry
} else { throw ex; }
} Prevention
- Let 'hadoop credential create' build keystore files; do not pre-create them with keytool defaults
- If using keytool, always pass -storetype jceks and never mix certificates into credential stores
- Pin one JVM version for all processes that write the store
When it happens
Trigger: Writing a credential into a store whose bytes are a JKS (or other type) file that was loaded under the jceks provider path; a .jceks-suffixed file actually created by keytool's default store type; keystore instance left uninitialized after a failed load; JVM provider set that cannot protect AES keys.
Common situations: Admin pre-created the file with 'keytool -genkeypair -keystore creds.jceks' (JKS content); mixing keystore tooling between keytool and hadoop credential; FIPS JVMs that disallow the JCEKS key-protection algorithm.
Related errors
- Can't get credential " + alias + " from " + getPathAsString(
- Can't get algorithm for credential " + alias + " from " + ge
- Can't recover credential " + alias + " from " + getPathAsStr
- Can't get alias " + alias + " from " + getPathAsString()
- Credential " + alias + " already exists in " + this
AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22).
Data as JSON: /api/errors/4f83469cdd835610.
Report an issue: GitHub.