apache/hadoop · error · DelegationTokenIOException
Failed to unmarshall token for {canonicalUri}
Error message
Failed to unmarshall token for {canonicalUri} What it means
If Token.decodeIdentifier() returns null instead of throwing (which Hadoop's Token does when the kind maps to no known identifier factory or decoding yields nothing), S3ADelegationTokens treats it as an unmarshalling failure and throws DelegationTokenIOException 'Failed to unmarshall token for <canonicalUri>' rather than NPE later. The canonical URI in the message identifies which filesystem the unusable token belongs to.
Source
Thrown at hadoop-tools/hadoop-aws/src/main/java/org/apache/hadoop/fs/s3a/auth/delegation/S3ADelegationTokens.java:592
throws IOException {
checkArgument(token != null, "null token");
AbstractS3ATokenIdentifier identifier;
// harden up decode beyond that Token does itself
try {
identifier = token.decodeIdentifier();
} catch (RuntimeException e) {
Throwable cause = e.getCause();
if (cause != null) {
// its a wrapping around class instantiation.
throw new DelegationTokenIOException("Decoding S3A token " + cause,
cause);
} else {
throw e;
}
}
if (identifier == null) {
throw new DelegationTokenIOException("Failed to unmarshall token for "
+ getCanonicalUri());
}
identifier.validate();
return identifier;
}
/**
* Return a string for use in building up the User-Agent field, so
* get into the S3 access logs. Useful for diagnostics.
* Delegates to {{@link AbstractDelegationTokenBinding#getUserAgentField()}}
* for the current binding.
* @return a string for the S3 logs or "" for "nothing to add"
*/
public String getUserAgentField() {
return tokenBinding.getUserAgentField();
}
/**View on GitHub (pinned to 2add963021)
Solutions
- Remove the token for that s3a URI from the credentials (new Credentials for the job, or cancel the token) and let the filesystem deploy unbonded
- Ensure the delegation-token binding that issued the token is on the classpath and configured on consumers
- Re-fetch a fresh token after aligning versions
Defensive patterns
Strategy: try-catch
Validate before calling
if (token.decodeIdentifier() == null) {
credentials.removeToken(token.getService());
LOG.warn("Token kind {} for {} cannot be decoded; removed", token.getKind(), token.getService());
} Try / catch
try {
tokens.bindToAnyDelegationToken();
} catch (DelegationTokenIOException e) {
if (e.getMessage().contains("Failed to unmarshall token")) {
credentials.removeToken(new Text(canonicalUri)); // unknown-kind token: purge and rebind
tokens.bindToAnyDelegationToken();
} else {
throw e;
}
} Prevention
- Remove foreign/legacy tokens from credentials stores when changing bindings
- Keep the issuing binding on the consumer classpath
- Periodically purge credential files of tokens for decommissioned services
When it happens
Trigger: A token of an unknown/unregistered kind (or with an empty payload) is present in the user's credentials for the s3a service, and decodeTokenIdentifier processes it during binding.
Common situations: Tokens from other S3A-compatible systems or old versions left in a credentials file; a token kind registered by a binding that is no longer on the classpath; partially written token stores.
Related errors
- Decoding S3A token {cause}
- Delegation token is wrong class; expected a token identifier
- No URI in {this}
- Incompatible EncryptionSecrets version: {versionId}
- No AWS credential providers created by Delegation Token Bind
AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22).
Data as JSON: /api/errors/5ab2d200396ab29c.
Report an issue: GitHub.