signalapp/Signal-Server · error · JsonParseException

Could not interpret identity key bytes as an EC public key

Error message

Could not interpret identity key bytes as an EC public key

What it means

Thrown by IdentityKeyAdapter during Jackson deserialization when a JSON field holds bytes that cannot be interpreted as an EC public key. The adapter wraps libsignal's InvalidKeyException in a JsonParseException so the failure surfaces as a JSON binding error. It indicates the supplied identity key material is malformed, the wrong length, or not a valid EC point.

Solutions

  1. Verify the source of the identity key bytes and regenerate/obtain them from a valid identity key pair.
  2. Check that the sender is encoding the key the same way the adapter expects (base64 string decoded to raw EC public key bytes).
  3. Confirm client and server library versions agree on identity key format (no protocol version mismatch).
  4. Inspect the raw bytes: a valid EC public key for this format is the compressed 33-byte or expected fixed-length encoding; fix truncation if length is wrong.
  5. Wrap deserialization in a try-catch for JsonParseException and reject the request with a 400 rather than a 500.

Example fix

// before (invalid payload)
{"identityKey": "not-a-real-key"}
// after (valid base64-encoded EC public key bytes)
{"identityKey": "BQBIQ6b3bBsVhS9pJwJciT2C0rOd7VCLb5Bt9eHwzO0R"}
Defensive patterns

Strategy: validation

Validate before calling

// before deserializing
byte[] keyBytes = Base64.getDecoder().decode(rawKey);
if (keyBytes.length != 33) {
    throw new IllegalArgumentException("Identity key must be 33-byte compressed EC point, got " + keyBytes.length);
}
if (keyBytes[0] != 0x05) {
    throw new IllegalArgumentException("Identity key must start with compressed-point prefix 0x05");
}

Try / catch

try {
    IdentityKey key = objectMapper.treeToValue(node, AccountAttributes.class);
} catch (JsonParseException e) {
    if (e.getCause() instanceof InvalidKeyException) {
        throw new BadRequestException("identity key is not a valid EC public key");
    }
    throw e;
}

Prevention

When it happens

Trigger: Deserializing a JSON payload whose identity key field is not valid base64-decoded EC public key bytes, e.g. truncated key material, an ed25519 key instead of an EC (x25519/derived EC) key, or corrupted bytes from a bad client payload.

Common situations: Clients sending identity keys in the wrong encoding after a protocol/version change; test fixtures with fake key bytes; payloads edited or truncated in transit; mixing identity key types (ACI vs PNI) from different account versions.

Understand the failure class

Background: "failed to unmarshal" / json.Unmarshal errors: why parsing a response into a Go struct fails and how to fix it — this error's family across 23 libraries.

Related errors


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

Appendix: source

Thrown at service/src/main/java/org/whispersystems/textsecuregcm/util/IdentityKeyAdapter.java:52

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

      try {
        identityKeyBytes = Base64.getDecoder().decode(parser.getValueAsString());
      } catch (final IllegalArgumentException e) {
        throw new JsonParseException(parser, "Could not parse identity key as a base64-encoded value", e);
      }

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

      try {
        return new IdentityKey(identityKeyBytes);
      } catch (final InvalidKeyException e) {
        throw new JsonParseException(parser, "Could not interpret identity key bytes as an EC public key", e);
      }
    }
  }
}

View on GitHub (pinned to 100ab61c82)