{"record":{"id":"359e058e45ec71c6","repo":"signalapp/Signal-Server","slug":"value-is-not-in-e164-format","errorCode":null,"errorMessage":"value is not in E164 format","messagePattern":"value is not in E164 format","errorType":"validation","errorClass":"FieldValidationException","httpStatus":null,"severity":"error","filePath":"service/src/main/java/org/whispersystems/textsecuregcm/grpc/validators/E164FieldValidator.java","lineNumber":32,"sourceCode":"public class E164FieldValidator extends FieldValidator<Boolean> {\n\n  public E164FieldValidator() {\n    super(\"e164\", Set.of(Descriptors.FieldDescriptor.Type.STRING), MissingOptionalAction.SUCCEED, false);\n  }\n\n  @Override\n  protected Boolean resolveExtensionValue(final Object extensionValue) throws FieldValidationException {\n    return requireFlagExtension(extensionValue);\n  }\n\n  @Override\n  protected void validateStringValue(\n      final Boolean extensionValue,\n      final String fieldValue) throws FieldValidationException {\n    try {\n      Util.requireNormalizedNumber(fieldValue);\n    } catch (final ImpossiblePhoneNumberException | NonNormalizedPhoneNumberException e) {\n      throw new FieldValidationException(\"value is not in E164 format\");\n    }\n  }\n}\n","sourceCodeStart":14,"sourceCodeEnd":36,"githubUrl":"https://github.com/signalapp/Signal-Server/blob/100ab61c82627582c867d19e1c0561ba2781e927/service/src/main/java/org/whispersystems/textsecuregcm/grpc/validators/E164FieldValidator.java#L14-L36","documentation":"E164FieldValidator checks that a proto field string is a normalized E.164 phone number via Util.requireNormalizedNumber. ImpossiblePhoneNumberException (unparseable) or NonNormalizedPhoneNumberException (parseable but not in strict E.164 form) result in FieldValidationException('value is not in E164 format').","triggerScenarios":"gRPC requests with phone number fields containing local formats, spaces/dashes/parentheses, missing '+' prefix, leading double zeros (0044...), or extensions.","commonSituations":"Users entering numbers from a contacts app in national format; clients skipping libphonenumber normalization before calling the API; numbers with country code but stray punctuation after device migration.","solutions":["Normalize with libphonenumber: PhoneNumberUtil.format(number, PhoneNumberFormat.E164) before sending","Ensure the value starts with '+' followed by country code and subscriber number, digits only","Strip spaces, dashes, parentheses, and extensions","Validate locally (parse + isPossibleNumber) before making the API call"],"exampleFix":"// before\nString e164 = \"(415) 555-2671\";\n// after\nString e164 = \"+14155552671\"; // via PhoneNumberUtil.format(..., E164)","handlingStrategy":"validation","validationCode":"PhoneNumberUtil util = PhoneNumberUtil.getInstance();\nPhonenumber.PhoneNumber n = util.parse(rawNumber, null);\nString e164 = util.format(n, PhoneNumberUtil.PhoneNumberFormat.E164);\nif (!e164.equals(rawNumber)) throw new IllegalArgumentException(\"number must be pre-normalized to E164: \" + e164);","typeGuard":"static boolean isE164(String s) { return s != null && s.matches(\"\\\\+\\\\d{1,15}\"); }","tryCatchPattern":"try {\n  grpcStub.callNumberField(e164);\n} catch (StatusRuntimeException e) {\n  if (e.getStatus().getCode() == Code.INVALID_ARGUMENT && e.getStatus().getDescription().contains(\"E164\")) {\n    // re-normalize with libphonenumber and retry\n  }\n}","preventionTips":["Run all user-entered numbers through libphonenumber normalizeDigitsOnly/format E164 before sending","Strip punctuation and extensions","Only accept numbers that already start with '+' plus digits"],"tags":["grpc","e164","phone-number","validation"],"backgroundTag":"invalid-identifier-format","analyzedSha":"100ab61c82627582c867d19e1c0561ba2781e927","analyzedAt":"2026-09-09T13:29:47.883Z","contentChangedAt":"2026-09-09T13:29:47.883Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}