{"record":{"id":"1e0dc45aa7f82efa","repo":"signalapp/Signal-Server","slug":"missing-credentials","errorCode":null,"errorMessage":"Missing credentials","messagePattern":"Missing credentials","errorType":"http","errorClass":"InvalidAuthorizationHeaderException","httpStatus":401,"severity":"error","filePath":"service/src/main/java/org/whispersystems/textsecuregcm/auth/BasicAuthorizationHeader.java","lineNumber":46,"sourceCode":"\n      final int spaceIndex = header.indexOf(' ');\n\n      if (spaceIndex == -1) {\n        throw new InvalidAuthorizationHeaderException(\"Invalid authorization header: \" + header);\n      }\n\n      final String authorizationType = header.substring(0, spaceIndex);\n\n      if (!\"Basic\".equals(authorizationType)) {\n        throw new InvalidAuthorizationHeaderException(\"Unsupported authorization method: \" + authorizationType);\n      }\n\n      final String credentials;\n\n      try {\n        credentials = new String(Base64.getDecoder().decode(header.substring(spaceIndex + 1)));\n      } catch (final IndexOutOfBoundsException e) {\n        throw new InvalidAuthorizationHeaderException(\"Missing credentials\");\n      }\n\n      if (StringUtils.isEmpty(credentials)) {\n        throw new InvalidAuthorizationHeaderException(\"Bad decoded value: \" + credentials);\n      }\n\n      final int credentialSeparatorIndex = credentials.indexOf(':');\n\n      if (credentialSeparatorIndex == -1) {\n        throw new InvalidAuthorizationHeaderException(\"Badly-formatted credentials: \" + credentials);\n      }\n\n      final String usernameComponent = credentials.substring(0, credentialSeparatorIndex);\n\n      final String username;\n      final byte deviceId;\n      {\n        final Pair<String, Byte> identifierAndDeviceId =","sourceCodeStart":28,"sourceCodeEnd":64,"githubUrl":"https://github.com/signalapp/Signal-Server/blob/100ab61c82627582c867d19e1c0561ba2781e927/service/src/main/java/org/whispersystems/textsecuregcm/auth/BasicAuthorizationHeader.java#L28-L64","documentation":"fromString throws InvalidAuthorizationHeaderException(\"Missing credentials\") when the substring after the first space is empty, so Base64 decoding's IndexOutOfBoundsException (begin index past end) is caught and rethrown. The header had a scheme but no credential part.","triggerScenarios":"Header value is exactly \"Basic \" with trailing space and nothing after; scheme present but credentials dropped by an intermediary.","commonSituations":"Header truncation at proxies or by manual header editing; template placeholders like \"Basic {{creds}}\" left unsubstituted.","solutions":["Append base64(username:password) after 'Basic '","Verify no proxy/gateway strips or truncates the Authorization header","Check client templating/config actually fills in the credentials"],"exampleFix":"// before\nAuthorization: Basic\n// after\nAuthorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=","handlingStrategy":"validation","validationCode":"int space = header.indexOf(' ');\nif (space == -1 || header.substring(space + 1).isEmpty()) throw new IllegalArgumentException(\"missing basic credentials\");","typeGuard":null,"tryCatchPattern":"try { BasicAuthorizationHeader.fromString(header); } catch (InvalidAuthorizationHeaderException e) { throw new NotAuthorizedException(\"Basic\"); }","preventionTips":["Check credential templating resolves before sending","Base64-encode a non-empty user:pass string"],"tags":["http-header","basic-auth","base64"],"backgroundTag":"missing-credentials","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"}