signalapp/Signal-Server · warning · StatusRuntimeException
INVALID_ARGUMENT
INVALID_ARGUMENT
Error message
extension requires a value to be set
What it means
The gRPC ValidatingInterceptor validates incoming protobuf messages against declarative field validators (extensions). For proto3 fields with explicit presence (optional), when a field is unset and the attached validator extension requires a value (getMissingOptionalAction() == FAIL), the interceptor rejects the request with INVALID_ARGUMENT and the message 'extension requires a value to be set'.
Solutions
- Set the flagged field explicitly in the client request — the error identifies the field/extension via the field violation detail.
- Regenerate client stubs from the current proto definitions so all validated fields are known and populated.
- If the field genuinely should be optional, change the validator extension's missingOptional action to SUCCEED (or VALIDATE_DEFAULT_VALUE) server-side.
- Run client-side validation with the same validator definitions before sending to catch violations early.
Example fix
// before: optional validated field left unset
MyRequest.newBuilder().setOtherField("x").build();
// after: always set presence-tracked validated fields
MyRequest.newBuilder()
.setOtherField("x")
.setRequiredByValidator("value") // field with missing_optional=FAIL extension
.build(); Defensive patterns
Strategy: validation
Validate before calling
// client-side, before sending
MyRequest req = MyRequest.newBuilder()...build();
for (var fd : req.getDescriptorForType().getFields()) {
if (fd.hasPresence() && !req.hasField(fd)) {
throw new IllegalArgumentException("Field with presence must be set: " + fd.getName());
}
} Type guard
boolean isFieldSet(com.google.protobuf.Message msg, Descriptors.FieldDescriptor fd) {
return !fd.hasPresence() || msg.hasField(fd);
} Try / catch
try {
stub.call(request);
} catch (StatusRuntimeException e) {
if (e.getStatus().getCode() == Status.Code.INVALID_ARGUMENT) {
// inspect trailers for fieldViolation naming the unset field and populate it
}
} Prevention
- Regenerate client stubs whenever server protos add optional-but-validated fields.
- Share validator extension definitions between client and server so requirements are visible to both.
- Add integration tests that send fully-populated requests for each RPC.
When it happens
Trigger: A gRPC client sends a request message where an `optional` field with a presence-requiring validator extension is left unset — e.g. omitting a required-by-policy field in a request proto while the server's validation extension sets missing_optional action to FAIL.
Common situations: Client SDKs generated from older protos that don't set the newly added optional field; clients constructing requests programmatically and skipping a field assumed optional; proto schema drift between client and server.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- string expected to be non-empty
- repeated field is expected to be non-empty
- message expected to be present
- value is not valid base64 url
- value is not in E164 format
AI-assisted analysis of signalapp/Signal-Server@100ab61c82 (2026-09-09).
Data as JSON: /api/errors/9c46a3cdebaa3123.
Report an issue: GitHub.
Appendix: source
Thrown at service/src/main/java/org/whispersystems/textsecuregcm/grpc/ValidatingInterceptor.java:141
// Checking for repeated fields also handles maps, because maps are syntax sugar for repeated MapEntries
// which themselves are Messages that will be recursively descended.
for (final Object o : list) {
validateMessage(o);
}
} else if (fd.hasPresence() && msg.hasField(fd)) {
// If the field has presence information and is present, recursively validate it. Not all fields have
// presence, but we only validate Message type fields anyway, which always have explicit presence.
validateMessage(msg.getField(fd));
}
}
}
private void validateField(final FieldValidator<?> validator, final Object extensionValue, final Message msg, final Descriptors.FieldDescriptor fd) {
// for the fields with an `optional` modifier, checking if the field was set
// and if not, checking if extension allows missing optional field
if (fd.hasPresence() && !msg.hasField(fd)) {
switch (validator.getMissingOptionalAction()) {
case FAIL -> throw fieldViolation(fd, validator.getExtensionName(), "extension requires a value to be set");
case SUCCEED -> {
return;
}
case VALIDATE_DEFAULT_VALUE -> {}
}
}
try {
validator.validate(extensionValue, fd, msg.getField(fd));
} catch (FieldValidationException e) {
throw fieldViolation(fd, validator.getExtensionName(), e.getMessage());
}
}
private void validateRepeatedElementConstraints(
final ElementConstraint elementConstraint,
final Message message,
final Descriptors.FieldDescriptor fd) {View on GitHub (pinned to 100ab61c82)