{"record":{"id":"cd4a44b691b8ebfe","repo":"signalapp/Signal-Server","slug":"call-type-not-specified","errorCode":null,"errorMessage":"Call type not specified","messagePattern":"Call type not specified","errorType":"validation","errorClass":"CallQualityInvalidArgumentsException","httpStatus":null,"severity":"warning","filePath":"service/src/main/java/org/whispersystems/textsecuregcm/metrics/CallQualitySurveyManager.java","lineNumber":169,"sourceCode":"          }\n\n          Metrics.counter(PUB_SUB_MESSAGE_COUNTER_NAME, \"success\", String.valueOf(throwable == null))\n              .increment();\n        });\n  }\n\n  @VisibleForTesting\n  static void validateRequest(final SubmitCallQualitySurveyRequest request) throws CallQualityInvalidArgumentsException {\n    if (request.getStartTimestamp() == 0) {\n      throw new CallQualityInvalidArgumentsException(\"Start timestamp not specified\", \"startTimestamp\");\n    }\n\n    if (request.getEndTimestamp() == 0) {\n      throw new CallQualityInvalidArgumentsException(\"End timestamp not specified\", \"endTimestamp\");\n    }\n\n    if (StringUtils.isBlank(request.getCallType())) {\n      throw new CallQualityInvalidArgumentsException(\"Call type not specified\", \"callType\");\n    }\n\n    if (StringUtils.isBlank(request.getCallEndReason())) {\n      throw new CallQualityInvalidArgumentsException(\"Call end reason not specified\", \"callEndReason\");\n    }\n  }\n}\n","sourceCodeStart":151,"sourceCodeEnd":177,"githubUrl":"https://github.com/signalapp/Signal-Server/blob/100ab61c82627582c867d19e1c0561ba2781e927/service/src/main/java/org/whispersystems/textsecuregcm/metrics/CallQualitySurveyManager.java#L151-L177","documentation":"validateRequest in CallQualitySurveyManager throws when the survey request's callType is null or blank. callType distinguishes audio vs video calls and is required for survey analysis. The CallQualityInvalidArgumentsException includes the field name callType for the client to correct.","triggerScenarios":"submitCallQualitySurvey called with a SubmitCallQualitySurveyRequest whose callType is missing, empty, or whitespace-only.","commonSituations":"Clients omitting callType in the survey payload; enum/string mapping regressions after client upgrades; manually crafted API calls or integration tests leaving the field out.","solutions":["Set callType to a valid value (e.g. \"audio\" or \"video\") in the request body","Have the client derive callType from the active call object rather than user input","Log/inspect the outgoing JSON to confirm callType is non-blank before submission"],"exampleFix":"// before\n{\"startTimestamp\": 1699999400, \"endTimestamp\": 1700000000}\n// after\n{\"startTimestamp\": 1699999400, \"endTimestamp\": 1700000000, \"callType\": \"audio\"}","handlingStrategy":"validation","validationCode":"if (!request.callType || request.callType.trim() === '') { throw new Error('callType must be a non-empty string (e.g. audio/video)'); }","typeGuard":"const hasCallType = (r) => typeof r.callType === 'string' && r.callType.trim().length > 0;","tryCatchPattern":"try { await submitCallQualitySurvey(request); } catch (CallQualityInvalidArgumentsException e) { if ('callType'.equals(e.getField())) { request.setCallType(inferCallTypeFromSession()); resubmit(); } }","preventionTips":["Derive callType from the call session object instead of optional user input","Keep client/server callType values in sync with the API enum","Validate the full survey payload before sending"],"tags":["api","validation","missing-field"],"backgroundTag":"empty-required-field","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"}