signalapp/Signal-Server · error · InvalidAuthorizationHeaderException

Bad decoded value:

Error message

Bad decoded value: 

What it means

After decoding, fromString throws InvalidAuthorizationHeaderException("Bad decoded value: <credentials>") when the decoded credential string is empty (StringUtils.isEmpty). The Base64 payload was valid but encoded an empty string.

Solutions

  1. Encode a non-empty 'username:password' string
  2. Validate username/password are present in client config before encoding
  3. Send the server-issued account identifier (e.g. E.164 number) and auth password

Example fix

// before
String creds = base64(user + ":" + pass); // both empty
// after
if (user.isEmpty() || pass.isEmpty()) throw new IllegalStateException("missing creds");
String creds = base64(user + ":" + pass);
Defensive patterns

Strategy: validation

Validate before calling

String decoded = new String(Base64.getDecoder().decode(credentialPart), StandardCharsets.UTF_8);
if (decoded.isEmpty()) throw new IllegalArgumentException("empty basic credentials");

Try / catch

try { BasicAuthorizationHeader.fromString(header); } catch (InvalidAuthorizationHeaderException e) { throw new NotAuthorizedException("Basic"); }

Prevention

When it happens

Trigger: Sending 'Basic ' + base64("") — e.g. an empty username:password; a client encoding nothing after building the credentials string incorrectly.

Common situations: Empty config values for username/password; client code that does base64(user + ":" + pass) where both are null/empty after String.valueOf(null) mishandling.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


AI-assisted analysis of signalapp/Signal-Server@100ab61c82 (2026-09-09). Data as JSON: /api/errors/4c846ec295386d43. Report an issue: GitHub.

Appendix: source

Thrown at service/src/main/java/org/whispersystems/textsecuregcm/auth/BasicAuthorizationHeader.java:50

        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 =
            AccountAuthenticator.getIdentifierAndDeviceId(usernameComponent);

        username = identifierAndDeviceId.first();
        deviceId = identifierAndDeviceId.second();

View on GitHub (pinned to 100ab61c82)