Catching "Curl error 28"

I’ve been trying to catch and/or hide this “Curl error 28: Operation timed out after 1000 milliseconds with 0 bytes received”. I’m using UnityWebRequest and I’m able to handle a timeout but the error shows up in logs and console anyways, I’ve tried with both Coroutines and just iterating the UnityWebRequestAsyncOperation but I can’t find where I could catch that ugly error.

using UnityEngine;
using UnityEngine.Networking;

public class RestClientTest : MonoBehaviour
{
    UnityWebRequest Request;
    UnityWebRequestAsyncOperation ActiveRequest;

    void Start()
    {
        MakeRequest();
    }

    private void Update()
    {
        UpdateActiveRequest();
    }

    private void MakeRequest()
    {
        Request = UnityWebRequest.Get("http://localhost:8081/api/");
        ActiveRequest = Request.SendWebRequest();
    }

    private void UpdateActiveRequest()
    {
        if (ActiveRequest.isDone)
        {
            Debug.Log("Request is done!");
            if (Request.isNetworkError || Request.isHttpError)
            {
                Debug.Log("Request has error");
            }
        }
        else
        {
            Debug.Log("Request is at " + 
               (ActiveRequest.progress * 100f).ToString("F2") + "%");
        }
    }
}

Is that even you? I think that’s just Unity editor barf… unless you think it’s coming as a result of you.

Is there any clue to be found from selecting it and looking at the callstack in the bottom of the console window?

This is an error Unity internal logs. You web request should come out as error, the message is logged for help (in some cases in contains some useful info).
Your code sample does not contain timeout, yet the error says it timed out after one second, which is VERY small timeout.

Kurt: yeah I definitely get the error from the UnityWebRequest but when you select the error you don’t get the usual info such as callstack or the line that originated the error.

Aurimas: you are right, I forgot to add the line where I’m adding a timeout. Turns out everything works much better when I don’t set a timeout even when I use an invalid or non-responsive address.

I will continue just using everything without a timeout but it would definitely be nice if those Curl errors could be caught and hidden, I understand they can be useful but you don’t always want to see them.

Hitting this myself. I have an admin app that pings 10 other IP addresses to check status. Responses don’t need to be immediate. I’m testing to see if the computers are present, a step above pinging them. The system works, but if the computer at the IP address is offline it times out and I get the Curl error.
The error must be triggered by a separate thread because there is no information about processes. Just the error on a single line. If I don’t set the timeout to a second or two the app will wait a full 30 seconds before reporting the error.
I’m guessing that these kinds of errors just get passed through.

I was trying to find something similar, I managed to hide those errors with this:

public static void SendRequest(UnityWebRequest request, Action<UnityWebRequest.Result> callback)
{
    SendRequestAsync(request, callback);
}

private static async void SendRequestAsync(UnityWebRequest request, Action<UnityWebRequest.Result> callback)
{
    try
    {
        var asyncOp = request.SendWebRequest();
        while (!asyncOp.isDone)
            await Task.Delay(200);
    }
    catch (Exception) {}
    
    if (callback != null)
        callback.Invoke(request.result);
}

Ignore my previous post, it doesn’t seem to work.

Seems like it doesn’t catch the errors because the SendWebRequest is async in another routine.

Shouldn’t this error be a regular log or warning? Not an error that can pause the game if the console Error Pause is on?

Because there doesn’t seem to be any way to catch it.

Seems like a really bad design of this function. Any plan to change it?

This is kinda ridiculous, but seems to solve it. It basically abort the request right before the timeout expires. I would suggest a timeout of at least 5 seconds.

public static async Task<bool> SendRequest(UnityWebRequest request)
{
        int wait = 0;
        int wait_max = request.timeout * 1000;
        request.timeout += 1; //Add offset to make sure it abort first

        var asyncOp = request.SendWebRequest();
        while (!asyncOp.isDone)
        {
            await Task.Delay(200);
            wait += 200;
            if (wait >= wait_max)
                request.Abort();
        }

        return request.result == UnityWebRequest.Result.Success;
}

I would strongly suggest Unity to change this error into a log or warning in future versions.

Yes the error really does not make any sense at all a simple warning would be just fine?!?

my ISP blocked sites categorised as games and when iam trying to download any package it shows error

This is ridiculous,but it work!!!!! thank you!!

    private readonly string[] ipServices = new string[]
    {
        "https://api.ipify.org",
        "https://checkip.amazonaws.com",
        "https://ifconfig.me/ip"
    };
    private string lastIP = null;
    private readonly float checkInterval = 1f;
    private Coroutine checkRoutine;

    void Start()
    {
        checkRoutine = StartCoroutine(CheckExternalIPRoutine());
    }
    void OnDestroy()
    {
        if (checkRoutine != null)
            StopCoroutine(checkRoutine);
    }
    IEnumerator CheckExternalIPRoutine()
    {
        while (true)
        {
            yield return StartCoroutine(GetExternalIP(ip =>
            {
                if (!string.IsNullOrEmpty(ip) && ip != lastIP)
                {
                    lastIP = ip;
                    Debug.Log($"External IP Update: {lastIP}"); ;
                }
            }));

            yield return new WaitForSeconds(checkInterval);
        }
    }
    IEnumerator GetExternalIP(Action<string> callback)
    {
        string foundIP = null;
        foreach (var url in ipServices)
        {
            using (UnityWebRequest request = UnityWebRequest.Get(url))
            {
                float wait = 0;
                request.timeout = 5;
                var asyncOp = request.SendWebRequest();
                while (!asyncOp.isDone)
                {
                    yield return new WaitForSeconds(0.02f);
                    wait += 0.02f;
                    if (wait >= 1)
                        request.Abort();
                }

                if (request.result == UnityWebRequest.Result.Success)
                {
                    foundIP = request.downloadHandler.text.Trim();
                    break; 
                }
            }

            if (foundIP != null)
                break;
        }
        callback?.Invoke(foundIP);
    } 
My script to check if the IP has changed,Ignored Curl error 28.