apache/rocketmq · error · AuthenticationException
datetime is null.
Error message
datetime is null.
What it means
Thrown while building the gRPC authentication context: the Authorization metadata header is present but the companion datetime metadata (GrpcConstants.DATE_TIME) is missing or empty. The datetime string is the content that gets HMAC-signed, so without it the server cannot verify the client signature. The builder therefore refuses to construct the context before any signature check happens.
Source
Thrown at auth/src/main/java/org/apache/rocketmq/auth/authentication/builder/DefaultAuthenticationContextBuilder.java:59
public class DefaultAuthenticationContextBuilder implements AuthenticationContextBuilder<DefaultAuthenticationContext> {
private static final String CREDENTIAL = "Credential";
private static final String SIGNATURE = "Signature";
@Override
public DefaultAuthenticationContext build(Metadata metadata, GeneratedMessageV3 request) {
try {
DefaultAuthenticationContext context = new DefaultAuthenticationContext();
context.setChannelId(metadata.get(GrpcConstants.CHANNEL_ID));
context.setRpcCode(request.getDescriptorForType().getFullName());
String authorization = metadata.get(GrpcConstants.AUTHORIZATION);
if (StringUtils.isEmpty(authorization)) {
return context;
}
String datetime = metadata.get(GrpcConstants.DATE_TIME);
if (StringUtils.isEmpty(datetime)) {
throw new AuthenticationException("datetime is null.");
}
String[] result = authorization.split(CommonConstants.SPACE, 2);
if (result.length != 2) {
throw new AuthenticationException("authentication header is incorrect.");
}
String[] keyValues = result[1].split(CommonConstants.COMMA);
for (String keyValue : keyValues) {
String[] kv = keyValue.trim().split(CommonConstants.EQUAL, 2);
int kvLength = kv.length;
if (kv.length != 2) {
throw new AuthenticationException("authentication keyValues length is incorrect, actual length={}.", kvLength);
}
String authItem = kv[0];
if (CREDENTIAL.equals(authItem)) {
String[] credential = kv[1].split(CommonConstants.SLASH);
int credentialActualLength = credential.length;
if (credentialActualLength == 0) {View on GitHub (pinned to 293f588571)
Solutions
- Set the datetime metadata on every gRPC call, e.g. metadata.put(GrpcConstants.DATE_TIME, datetime) where datetime is the same string used when computing the client signature (typically formatted with DateTimeFormatter ofPattern('yyyyMMddHHmmss') in UTC).
- Use the official RocketMQ gRPC client SDK, which sets both authorization and datetime automatically in its credentials interceptor, instead of hand-writing the metadata.
- Verify no intermediary (gRPC proxy, custom ClientInterceptor, metadata whitelist) strips the datetime key between client and broker.
Example fix
// before
Metadata metadata = new Metadata();
metadata.put(Metadata.Key.of("authorization", ASCII_STRING_MARSHALLER), authHeader);
// signature computed over a local datetime variable
// after
String datetime = LocalDateTime.now(ZoneOffset.UTC).format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
Metadata metadata = new Metadata();
metadata.put(Metadata.Key.of("datetime", ASCII_STRING_MARSHALLER), datetime);
metadata.put(Metadata.Key.of("authorization", ASCII_STRING_MARSHALLER), "RocketMQ Credential=" + username + ",Signature=" + signature + ",DateTime=" + datetime); Defensive patterns
Strategy: validation
Validate before calling
// Before the gRPC call: ensure datetime metadata accompanies the authorization header
String datetime = DateTimeFormatter.ofPattern("yyyyMMddHHmmss")
.withZone(ZoneOffset.UTC).format(Instant.now());
if (authorizationHeader != null && !authorizationHeader.isEmpty()
&& (datetime == null || datetime.isEmpty())) {
throw new IllegalStateException("datetime metadata is required when authorization is set");
} Try / catch
catch (AuthenticationException e) when e.getMessage().contains("datetime is null") -> client-side: attach datetime metadata and retry once; surface otherwise. Prevention
- Centralize metadata construction in one client interceptor that always sets authorization and datetime together
- Compute the signature over the exact datetime string you put into metadata
- Add a unit test asserting both metadata keys are present on every outgoing call
When it happens
Trigger: A gRPC client (e.g. RocketMQ 5.x remoting gRPC SDK) sends the 'authorization' metadata key but omits the 'datetime' metadata key, or sends it with an empty value. Triggered on any authenticated gRPC RPC once AUTHORIZATION is set, because datetime is checked immediately after a non-empty authorization header.
Common situations: Hand-rolled gRPC clients or custom interceptors that only copy the authorization header; SDK versions where the signer sets datetime but a proxy/loan balancer strips unknown metadata keys; client code that builds metadata manually and forgets the datetime entry that the signature was computed over.
Related errors
- authentication header is incorrect.
- username cannot be null.
- User:{} is not found.
- authentication keyValues length is incorrect, actual length=
- authentication credential length is incorrect, actual length
AI-assisted analysis of apache/rocketmq@293f588571 (2026-08-14).
Data as JSON: /api/errors/a37fd1aa48dd8264.
Report an issue: GitHub.