Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.

Bug "WebRequestException: Request timeout" on Services.Authentication.AuthenticationServiceInternal

Discussion in 'Authentication' started by Mest, Dec 17, 2022.

  1. Mest

    Mest

    Joined:
    Nov 7, 2012
    Posts:
    14
    Hello everybody,
    we managed to upgrade our Unity to the "latest" 2022 version (2022.1.17f1) and upgraded every unity-pack. Since we now have to Authenticate the users (for RemoteConfig/Ads/IAP) we implemented it, like the documentations mentioning.

    Since the implementation, we have a tremendous rise of our exceptions because of the authentication-system (the second high one is the "System.Collections.Generic.Dictionary`2[TKey,TValue].TryInsert"-
    TelemetryHandler one, that's another story).

    I post this screenshot attached, as I start thinking, this might have something to do with traffic? If you look at the hour-graph you may understand why i came to this conclusion.
    upload_2022-12-17_11-26-12.png

    I am not able to reproduce this exception and I don't know if this is a critical exception for IAP's or other game-relevant stuff.

    I want to implement more of the UGS-features (without fearing it doesn't work like intended) and I just hope maybe someone can help me or deliver some suggestions, leading to a new perspective/solution-attempt.

    -----

    Here's the stacktrace:

    Unity.Services.Authentication.AuthenticationServiceInternal/<HandleSignInRequestAsync>d__108.MoveNext() (at D:/XXX/Library/PackageCache/com.unity.services.authentication@2.3.1/Runtime/AuthenticationServiceInternal.cs:528)
    Unity.Services.Authentication.WebRequest/<SendAsync>d__15`1<System.Object>.MoveNext() (at D:/XXX/Library/PackageCache/com.unity.services.authentication@2.3.1/Runtime/Network/WebRequest.cs:63)
    TMPro.TMP_TextProcessingStack`1<Unity.IL2CPP.Metadata.__Il2CppFullySharedGenericType>.PreviousItem() (at D:/XXX/Library/PackageCache/com.unity.textmeshpro@3.0.6/Scripts/Runtime/TMP_TextProcessingStack.cs:397)
    TMPro.TMP_TextProcessingStack`1<Unity.IL2CPP.Metadata.__Il2CppFullySharedGenericType>.PreviousItem() (at D:/XXX/Library/PackageCache/com.unity.textmeshpro@3.0.6/Scripts/Runtime/TMP_TextProcessingStack.cs:397)
    Unity.Services.Authentication.WebRequest.RequestCompleted(System.Threading.Tasks.TaskCompletionSource`1<System.String>,System.Int64,System.Boolean,System.Boolean,System.String,System.String,System.Collections.Generic.IDictionary`2<System.String,System.String>) (at D:/EXXX/Library/PackageCache/com.unity.services.authentication@2.3.1/Runtime/Network/WebRequest.cs:193)
    Unity.Services.Authentication.WebRequest/<>c__DisplayClass16_0.<SendAttemptAsync>b__0(UnityEngine.AsyncOperation) (at D:/XXX/Library/PackageCache/com.unity.services.authentication@2.3.1/Runtime/Network/WebRequest.cs:82)


    And here's my implementation-Code:
    Code (CSharp):
    1. private bool isTryingToInit = false;
    2.         private bool isInitialized = false;
    3.  
    4.         private UnityAction<bool> onConnectionOutcomeEvent;
    5.  
    6.         private const string environment = "production";
    7.  
    8.         private bool HasConnection {
    9.             get {
    10.                 return (Application.internetReachability != NetworkReachability.NotReachable);
    11.                 //retrun Unity.Services.RemoteConfig.Utilities.CheckForInternetConnection(); //thats a "http"-call??? - no, thanks
    12.             }
    13.         }
    14.  
    15.         public void TryConnectWithUnityService(UnityAction<bool> _onConnecitonOutcome) {
    16.             if (isInitialized) {
    17.                 if (_onConnecitonOutcome != null) {
    18.                     _onConnecitonOutcome.Invoke(true);
    19.                 }
    20.                 return;
    21.             }
    22.             if (isTryingToInit) {
    23.                 if (_onConnecitonOutcome != null) {
    24.                     onConnectionOutcomeEvent -= _onConnecitonOutcome;
    25.                     onConnectionOutcomeEvent += _onConnecitonOutcome;
    26.                 }
    27.                 return;
    28.             }
    29.             isTryingToInit = true;
    30.  
    31.             if (!HasConnection) {
    32.  
    33.                 isTryingToInit = false;
    34.                 if (_onConnecitonOutcome != null) {
    35.                     _onConnecitonOutcome.Invoke(false);
    36.                 }
    37.                 return;
    38.             }
    39.  
    40.             if (_onConnecitonOutcome != null) {
    41.                 onConnectionOutcomeEvent -= _onConnecitonOutcome;
    42.                 onConnectionOutcomeEvent += _onConnecitonOutcome;
    43.             }
    44.             StartConnectingUnityService();
    45.         }
    46.  
    47.         private async void StartConnectingUnityService() {
    48.             await InitializeAndSignInAsync();
    49.        
    50.             isInitialized = (UnityServices.State == ServicesInitializationState.Initialized);
    51.             isTryingToInit = false;
    52.             if(onConnectionOutcomeEvent != null) {
    53.                 UnityAction<bool> _tempHolder = onConnectionOutcomeEvent;
    54.                 onConnectionOutcomeEvent = null;
    55.                 _tempHolder.Invoke(isInitialized);
    56.             }
    57.         }
    58.  
    59.         private async Task InitializeAndSignInAsync() {
    60.             // initialize handlers for unity game services
    61.             if (!isInitialized) {
    62.                 if ((UnityServices.State == ServicesInitializationState.Uninitialized)) {
    63.                     try {
    64.                         // options can be passed in the initializer, e.g if you want to set analytics-user-id or an environment-name use the lines from below:
    65.                         // var options = new InitializationOptions()
    66.                         //   .SetOption("com.unity.services.core.analytics-user-id", "my-user-id-1234")
    67.                         //   .SetOption("com.unity.services.core.environment-name", "production");
    68.                         var _options = new InitializationOptions()
    69.                         .SetEnvironmentName(environment);
    70.  
    71.                         await UnityServices.InitializeAsync(_options);
    72.                     } catch (System.Exception _ex) {
    73.  
    74.                         return;
    75.                     }
    76.                 }
    77.             }
    78.  
    79.             // remote config requires authentication for managing environment information
    80.             if (!AuthenticationService.Instance.IsSignedIn) {
    81.                 try {
    82.                     await AuthenticationService.Instance.SignInAnonymouslyAsync();
    83.                 } catch (AuthenticationException ex) {
    84.                     // Compare error code to AuthenticationErrorCodes
    85.                     // Notify the player with the proper error message
    86.                     Debug.LogException(ex);
    87.                 } catch (RequestFailedException ex) {
    88.                     // Compare error code to CommonErrorCodes
    89.                     // Notify the player with the proper error message
    90.                     Debug.LogException(ex);
    91.                 } catch (System.Exception _ex) {
    92.  
    93.                     return;
    94.                 }
    95.             }
    96.  
    97.  
    98.         }

    Relevant Packages we use:
    • Advertisement 4.3.0
    • Analytics 4.2.0
    • Analytics Library 3.8.1
    • Authentication 2.3.1
    • In App Purchasing 4.5.1
    • Remote Config 3.1.3
    Other relevant Informations:
    • We use IL2CPP
    • We use proguard
     
    Last edited: Dec 17, 2022
  2. erickb_unity

    erickb_unity

    Unity Technologies

    Joined:
    Sep 1, 2021
    Posts:
    28
    Hello,

    At first glance, I will say network exceptions are common, especially on mobile where the data connection can be unstable or slow.

    Everytime you use Debug.LogException, the exception will be sent to Cloud Diagnostics.

    For exceptions related to network errors (no network, timeout, etc.), I suggest avoiding logging these as exceptions.

    (You can use Debug.LogError(exception.Message) in these cases if you want to keep the logs without the exception being sent to cloud diagnostics)

    Could you provide your organization and project id so we can do a more in-depth analysis?
     
    Last edited: Dec 22, 2022
  3. Mest

    Mest

    Joined:
    Nov 7, 2012
    Posts:
    14
    Thanks for the info about
    Code (CSharp):
    1. Debug.LogException(exception)
    I changed those 2 to
    Code (CSharp):
    1. Debug.LogWarning(exception)
    I'll PM you the organization and project id.
     
  4. tessellation

    tessellation

    Joined:
    Aug 11, 2015
    Posts:
    359
    Hi @erickb_unity. An issue related to this is that WebRequestException is marked as an internal Exception-derived class to the Unity.Services.Authentication namespace. So it's not easy (without reflection) to catch this particular exception.

    In other words, I prefer to do:
    Code (CSharp):
    1. if (ex is WebRequestException)
    2. // or
    3. catch(WebRequestException ex)
    4. // instead of
    5. if (ex.GetType().FullName == "Unity.Services.Authentication.WebRequestException")
     
  5. erickb_unity

    erickb_unity

    Unity Technologies

    Joined:
    Sep 1, 2021
    Posts:
    28
    Hello, the WebRequestException should never be thrown from our apis. If you are catching it, can you let us know in what situation this is thrown?

    WebRequestException are handled in the internal service logic and should always be converted to an AuthenticationException or RequestFailedException depending on the error.
     
  6. tessellation

    tessellation

    Joined:
    Aug 11, 2015
    Posts:
    359
    Thanks @erickb_unity . That is strange then. It's showing up on our Unity Cloud Diagnostics. We logged the exception because it's caught in our code (unhandled by yours) after awaiting on
    AuthenticationService.Instance.SignInAnonymouslyAsync(). This log should help you track it down...

    Log Message  Mar 20, 2023, 13:55:04.942  [UnityGameServices] Result of internet reach check: True
    Log Message Mar 20, 2023, 13:55:06.606 [IAP_Store] Created static IAP store singleton
    Log Message Mar 20, 2023, 13:55:06.607 [IAP_Store] Init Unity IAP v4.7.0 for GooglePlay with 10 products
    Error Mar 20, 2023, 13:55:09.441 Curl error 60: Cert verify failed: UNITYTLS_X509VERIFY_FLAG_USER_ERROR1
    Error Mar 20, 2023, 13:55:10.001 Curl error 28: SSL connection timeout
    Warning Mar 20, 2023, 13:55:10.010 [Authentication]: Network error detected, retrying...
    Error Mar 20, 2023, 13:55:15.012 Curl error 28: Operation timed out after 4999 milliseconds with 0 bytes received
    Warning Mar 20, 2023, 13:55:15.038 [Authentication]: Network error detected, retrying...
    Error Mar 20, 2023, 13:55:20.041 Curl error 28: Operation timed out after 4999 milliseconds with 0 bytes received
    Log Message Mar 20, 2023, 13:55:20.067 [Authentication]: Request failed: 0, Request timeout


    Notice first that our code (UnityGameServices) performs an HttpWebRequest to "https://unity.com" and that succeeds (first line). Meanwhile both the GooglePlayGames plugin (not shown, but it was previously in the log) and Unity IAP are able to connect and authenticate. Then Curl errors start appearing which I believe are from Unity Authentication Service. The last line with the timeout is then logged and then after, the exception is thrown with WebRequestException.Message = "Request timeout."

    Package versions:
    • Unity Authentication v2.4.0
    • Services Core 1.8.1