signalapp/Signal-Server · error · JsonParseException

Could not parse public key as a base64-encoded value

Error message

Could not parse public key as a base64-encoded value

What it means

Thrown inside a Jackson JsonDeserializer when the JSON string value of a public-key field is not valid Base64: Base64.getDecoder().decode raises IllegalArgumentException, which is caught, counted via an 'illegal-base64' metrics counter, and rethrown as a JsonParseException. The faulting input is the JSON property being deserialized, so the whole deserialization (and hence the request consuming the config payload) fails.

Solutions

  1. Ensure the JSON field containing the public key is a valid Base64 string (standard Base64, not URL-safe or hex)
  2. Verify the client serializes the key with Base64.getEncoder().encodeToString(key.serialize()) before sending
  3. Check that the value is not null, empty, or wrapped in quotes incorrectly in the request payload
Defensive patterns

Strategy: try-catch

When it happens

Trigger: Thrown at service/src/main/java/org/whispersystems/textsecuregcm/util/AbstractPublicKeyDeserializer.java:27 when the library encounters an invalid state.

Common situations: See trigger scenarios.


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

Appendix: source

Thrown at service/src/main/java/org/whispersystems/textsecuregcm/util/AbstractPublicKeyDeserializer.java:27

import io.micrometer.core.instrument.Metrics;
import org.signal.libsignal.protocol.InvalidKeyException;
import org.whispersystems.textsecuregcm.metrics.MetricsUtil;

abstract class AbstractPublicKeyDeserializer<K> extends JsonDeserializer<K> {

  private final String invalidKeyCounterName = MetricsUtil.name(getClass(), "invalidKey");

  private static final String REASON_TAG_NAME = "reason";

  @Override
  public K deserialize(final JsonParser parser, final DeserializationContext context) throws IOException {
    final byte[] publicKeyBytes;

    try {
      publicKeyBytes = Base64.getDecoder().decode(parser.getValueAsString());
    } catch (final IllegalArgumentException e) {
      Metrics.counter(invalidKeyCounterName, REASON_TAG_NAME, "illegal-base64").increment();
      throw new JsonParseException(parser, "Could not parse public key as a base64-encoded value", e);
    }

    if (publicKeyBytes.length == 0) {
      return null;
    }

    try {
      return deserializePublicKey(publicKeyBytes);
    } catch (final InvalidKeyException e) {
      Metrics.counter(invalidKeyCounterName, REASON_TAG_NAME, "invalid-key").increment();
      throw new JsonParseException(parser, "Could not interpret key bytes as a public key", e);
    }
  }

  protected abstract K deserializePublicKey(final byte[] publicKeyBytes) throws InvalidKeyException;
}

View on GitHub (pinned to 100ab61c82)