signalapp/Signal-Server · error · ObsoletePhoneNumberFormatException
bj
Error message
bj
What it means
canonicalizePhoneNumber throws ObsoletePhoneNumberFormatException with message "bj" when the given number matches Signal's old Benin phone number format. Benin changed its numbering plan (old 8-digit numbers were prefixed), so numbers in the legacy format are deliberately rejected instead of being silently canonicalized. Callers must migrate the number to the new format or reject the account identifier.
Solutions
- Reformat the number to Benin's new numbering plan (prefix the old national number per the regulator's migration rule, e.g. prepend the mandated digit(s)) before canonicalizing.
- Have the user re-register/update their phone number to the new format.
- Catch ObsoletePhoneNumberFormatException and treat the identifier as obsolete: prompt for re-verification rather than sending to the old number.
- Update stored records via a migration that rewrites legacy Benin numbers to the new format.
- Exclude obsolete-format numbers from bulk operations and log them for remediation.
Example fix
// before
Phonenumber.PhoneNumber n = phoneUtil.parse("+229 90 12 34 56", null);
Phonenumber.PhoneNumber canonical = Util.canonicalizePhoneNumber(n); // throws
// after
Phonenumber.PhoneNumber n = phoneUtil.parse("+229 0190 12 34 56", null);
Phonenumber.PhoneNumber canonical = Util.canonicalizePhoneNumber(n); // new numbering plan Defensive patterns
Strategy: validation
Validate before calling
// before canonicalizing
Phonenumber.PhoneNumber n = phoneUtil.parse(raw, null);
if (n.getCountryCode() == 229 && String.valueOf(n.getNationalNumber()).length() == 8) {
// legacy Benin format: apply the regulator's migration prefix first
n = new Phonenumber.PhoneNumber().setCountryCode(229)
.setNationalNumber(Long.parseLong("01" + n.getNationalNumber()));
}
Phonenumber.PhoneNumber canonical = Util.canonicalizePhoneNumber(n); Try / catch
try {
canonical = Util.canonicalizePhoneNumber(number);
} catch (ObsoletePhoneNumberFormatException e) {
// "bj": legacy Benin numbering plan
markNumberObsolete(number);
throw new WebApplicationException(Status.BAD_REQUEST);
} Prevention
- Track national numbering-plan changes (Benin 2024 prefix migration) in a data migration
- Re-verify Benin accounts registered before the numbering change
- Never silently rewrite phone numbers; route obsolete formats to an explicit migration path
- Log ObsoletePhoneNumberFormatException occurrences to find un-migrated records
When it happens
Trigger: Calling Util.canonicalizePhoneNumber with a Phonenumber.PhoneNumber whose national number matches the legacy Benin (country code 229) pattern detected by isOldFormatBeninPhoneNumber, e.g. an 8-digit Benin subscriber number from before the 2024 numbering change.
Common situations: Long-lived accounts registered with old Benin numbers; data imported from old backups; clients that never re-registered after Benin's numbering plan change; bulk migration scripts processing pre-change contact lists.
Understand the failure class
Background: "is deprecated and will be removed" — deprecation warnings for old API names, keywords, and options, and how to migrate before the removal release — this error's family across 29 libraries.
Related errors
- could not parse already validated number
- value is not in E164 format
- return Response.status(499).build();
AI-assisted analysis of signalapp/Signal-Server@100ab61c82 (2026-09-09).
Data as JSON: /api/errors/70a07f64db7ffec8.
Report an issue: GitHub.
Appendix: source
Thrown at service/src/main/java/org/whispersystems/textsecuregcm/util/Util.java:239
* @param phoneNumber the phone number to check.
* @return whether the provided phone number is an old-format Benin phone number
*/
public static boolean isOldFormatBeninPhoneNumber(final Phonenumber.PhoneNumber phoneNumber) {
return "BJ".equals(PHONE_NUMBER_UTIL.getRegionCodeForNumber(phoneNumber)) &&
PHONE_NUMBER_UTIL.getNationalSignificantNumber(phoneNumber).length() == 8;
}
/**
* If applicable, return the canonical form of the provided phone number.
* This is relevant in cases where a numbering authority has changed the numbering format for a region.
*
* @param phoneNumber the phone number to canonicalize.
* @return the canonical phone number if applicable, otherwise the original phone number.
*/
public static Phonenumber.PhoneNumber canonicalizePhoneNumber(final Phonenumber.PhoneNumber phoneNumber)
throws NumberParseException, ObsoletePhoneNumberFormatException {
if (isOldFormatBeninPhoneNumber(phoneNumber)) {
throw new ObsoletePhoneNumberFormatException("bj");
}
return phoneNumber;
}
public static byte[] truncate(byte[] element, int length) {
byte[] result = new byte[length];
System.arraycopy(element, 0, result, 0, result.length);
return result;
}
public static void sleep(long i) {
try {
Thread.sleep(i);
} catch (final InterruptedException ignored) {
}
}
View on GitHub (pinned to 100ab61c82)