signalapp/Signal-Server · error · JsonParseException
Could not parse string as a base64-encoded value
Error message
Could not parse string as a base64-encoded value
What it means
Thrown by BackupAuthCredentialAdapter's GenericDeserializer when the JSON string value cannot be decoded as Base64. The IllegalArgumentException from Base64.getDecoder().decode is caught, the INVALID_BASE64_COUNTER metric is incremented, and a JsonParseException is raised, so the field fails Jackson deserialization. The faulting input is the malformed Base64 string supplied for a BackupAuth credential field.
Solutions
- Ensure the JSON field is a valid standard-Base64 string before submitting
- Confirm the client encodes the backup auth credential bytes with Base64.getEncoder().encodeToString(...)
- Check the payload is not empty, truncated, or containing whitespace/URL-safe Base64 characters
Defensive patterns
Strategy: try-catch
When it happens
Trigger: Thrown at service/src/main/java/org/whispersystems/textsecuregcm/util/BackupAuthCredentialAdapter.java:44 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/b1f334872b5f362d.
Report an issue: GitHub.
Appendix: source
Thrown at service/src/main/java/org/whispersystems/textsecuregcm/util/BackupAuthCredentialAdapter.java:44
private static final Counter INVALID_BASE64_COUNTER =
Metrics.counter(MetricsUtil.name(BackupAuthCredentialAdapter.class, "invalidBase64"));
private static final Counter INVALID_BYTES_COUNTER =
Metrics.counter(MetricsUtil.name(BackupAuthCredentialAdapter.class, "invalidBackupAuthObject"));
abstract static class GenericDeserializer<T> extends JsonDeserializer<T> {
abstract T deserialize(final byte[] bytes) throws InvalidInputException;
@Override
public T deserialize(final JsonParser parser, final DeserializationContext deserializationContext)
throws IOException {
final byte[] bytes;
try {
bytes = Base64.getDecoder().decode(parser.getValueAsString());
} catch (final IllegalArgumentException e) {
INVALID_BASE64_COUNTER.increment();
throw new JsonParseException(parser, "Could not parse string as a base64-encoded value", e);
}
try {
return deserialize(bytes);
} catch (InvalidInputException e) {
INVALID_BYTES_COUNTER.increment();
throw new JsonParseException(parser, "Could not interpret bytes as a BackupAuth object");
}
}
}
static class GenericSerializer<T extends ByteArray> extends JsonSerializer<T> {
@Override
public void serialize(final T t, final JsonGenerator jsonGenerator, final SerializerProvider serializerProvider)
throws IOException {
jsonGenerator.writeString(Base64.getEncoder().encodeToString(t.serialize()));
}
}View on GitHub (pinned to 100ab61c82)