signalapp/Signal-Server · error · InvalidAuthorizationHeaderException
Missing credentials
Error message
Missing credentials
What it means
fromString throws InvalidAuthorizationHeaderException("Missing credentials") when the substring after the first space is empty, so Base64 decoding's IndexOutOfBoundsException (begin index past end) is caught and rethrown. The header had a scheme but no credential part.
Solutions
- Append base64(username:password) after 'Basic '
- Verify no proxy/gateway strips or truncates the Authorization header
- Check client templating/config actually fills in the credentials
Example fix
// before Authorization: Basic // after Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=
Defensive patterns
Strategy: validation
Validate before calling
int space = header.indexOf(' ');
if (space == -1 || header.substring(space + 1).isEmpty()) throw new IllegalArgumentException("missing basic credentials"); Try / catch
try { BasicAuthorizationHeader.fromString(header); } catch (InvalidAuthorizationHeaderException e) { throw new NotAuthorizedException("Basic"); } Prevention
- Check credential templating resolves before sending
- Base64-encode a non-empty user:pass string
When it happens
Trigger: Header value is exactly "Basic " with trailing space and nothing after; scheme present but credentials dropped by an intermediary.
Common situations: Header truncation at proxies or by manual header editing; template placeholders like "Basic {{creds}}" left unsubstituted.
Related errors
- Blank header
- Invalid authorization header:
- Unsupported authorization method:
- access key length must be 16
- Bad decoded value:
AI-assisted analysis of signalapp/Signal-Server@100ab61c82 (2026-09-09).
Data as JSON: /api/errors/1e0dc45aa7f82efa.
Report an issue: GitHub.
Appendix: source
Thrown at service/src/main/java/org/whispersystems/textsecuregcm/auth/BasicAuthorizationHeader.java:46
final int spaceIndex = header.indexOf(' ');
if (spaceIndex == -1) {
throw new InvalidAuthorizationHeaderException("Invalid authorization header: " + header);
}
final String authorizationType = header.substring(0, spaceIndex);
if (!"Basic".equals(authorizationType)) {
throw new InvalidAuthorizationHeaderException("Unsupported authorization method: " + authorizationType);
}
final String credentials;
try {
credentials = new String(Base64.getDecoder().decode(header.substring(spaceIndex + 1)));
} catch (final IndexOutOfBoundsException e) {
throw new InvalidAuthorizationHeaderException("Missing credentials");
}
if (StringUtils.isEmpty(credentials)) {
throw new InvalidAuthorizationHeaderException("Bad decoded value: " + credentials);
}
final int credentialSeparatorIndex = credentials.indexOf(':');
if (credentialSeparatorIndex == -1) {
throw new InvalidAuthorizationHeaderException("Badly-formatted credentials: " + credentials);
}
final String usernameComponent = credentials.substring(0, credentialSeparatorIndex);
final String username;
final byte deviceId;
{
final Pair<String, Byte> identifierAndDeviceId =View on GitHub (pinned to 100ab61c82)