{"record":{"id":"b2c786f5cd8bf3af","repo":"signalapp/Signal-Server","slug":"value-is-not-valid-base64-url","errorCode":null,"errorMessage":"value is not valid base64 url","messagePattern":"value is not valid base64 url","errorType":"validation","errorClass":"FieldValidationException","httpStatus":null,"severity":"error","filePath":"service/src/main/java/org/whispersystems/textsecuregcm/grpc/validators/Base64UrlFieldValidator.java","lineNumber":32,"sourceCode":"public class Base64UrlFieldValidator extends FieldValidator<Boolean> {\n\n  public Base64UrlFieldValidator() {\n    super(\"base64url\", 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      Base64.getUrlDecoder().decode(fieldValue);\n    } catch (IllegalArgumentException e) {\n      throw new FieldValidationException(\"value is not valid base64 url\");\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/Base64UrlFieldValidator.java#L14-L36","documentation":"Base64UrlFieldValidator validates that a proto field value is decodable base64url. It runs java.util.Base64.getUrlDecoder().decode on the string and throws FieldValidationException('value is not valid base64 url') on IllegalArgumentException, causing the gRPC request to be rejected.","triggerScenarios":"gRPC requests (e.g. receipts, backup, account fields annotated with this validator) carrying a string field that is empty, standard base64 with '+'/'/', hex-encoded, or otherwise not valid base64url (A-Z, a-z, 0-9, '-', '_').","commonSituations":"Clients using standard base64 instead of base64url, hex or raw bytes encoded as a string, corrupted/truncated values from key derivation code, double encoding.","solutions":["Encode the value with URL-safe base64 (no padding issues: use base64url with or without padding as the schema expects)","Replace '+' with '-' and '/' with '_' if you only have standard base64","Check that you are not sending hex (bytesToHex) where base64url is expected","Inspect the offending field value for whitespace, quotes, or truncation before sending"],"exampleFix":"// before\nString encoded = Base64.getEncoder().encodeToString(bytes);\n// after\nString encoded = Base64.getUrlEncoder().encodeToString(bytes);","handlingStrategy":"validation","validationCode":"boolean isValidBase64Url(String s) {\n  if (s == null || s.isEmpty()) return false;\n  try { Base64.getUrlDecoder().decode(s); return true; } catch (IllegalArgumentException e) { return false; }\n}","typeGuard":null,"tryCatchPattern":"try {\n  grpcStub.call(request);\n} catch (StatusRuntimeException e) {\n  if (e.getStatus().getCode() == Code.INVALID_ARGUMENT && e.getStatus().getDescription().contains(\"base64 url\")) {\n    // re-encode the offending field with Base64.getUrlEncoder()\n  }\n}","preventionTips":["Use Base64.getUrlEncoder() (not getEncoder() or hex) for fields validated as base64url","Trim whitespace from values before encoding","Add a client-side validator mirroring server-side proto annotations"],"tags":["grpc","base64url","validation","proto"],"backgroundTag":"invalid-argument-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"}