Memory Leak on UnityWebRequest even with disposing

I have this wrapper to call the OpenAI API, returning a class with an action to subscribe to in it. I am sure I am doing everything properly with regards to memory management, so I don’t know why I keep getting “Native Collection has not been disposed”. I have been looking for other forum posts about this, and they all haven’t been disposing - but I have. Any help appreciated!

   //actual function to be called, returning a subscribable action in a class 
    public static APIAction Generate(string prompt, string dummy = null)
    {
        Debug.Log(prompt);
        APICall obj = new APICall()
        {
            messages = new[] { new APIMessage() { role = "user", content = prompt } },
            model = "gpt-3.5-turbo",
            temperature = 0.7f
        };
        string jsonData = JsonUtility.ToJson(obj);

        Byte[] postData = System.Text.Encoding.UTF8.GetBytes(jsonData);

        UnityWebRequest _request = UnityWebRequest.Post("https://api.openai.com/v1/chat/completions", "POST");
        _request.uploadHandler = new UploadHandlerRaw(postData);
        _request.downloadHandler = new DownloadHandlerBuffer();
        _request.disposeUploadHandlerOnDispose = true;
        _request.disposeDownloadHandlerOnDispose = true;
        _request.SetRequestHeader("Content-Type", "application/json");
        _request.SetRequestHeader("Authorization", "Bearer " + GetKey);

        APIAction temp = new APIAction();

        Call(_request, text =>
        {
            Root response = JsonUtility.FromJson<Root>(text);
            temp.Response?.Invoke(response);
           
        }, dummy);


        return temp;
    }

    delegate void AsyncAction(string response);
    //func to actually send the request, abstracted so I can pass in a dummy response for testing (as I don't want to waste money)
    static void Call(UnityWebRequest _request, AsyncAction action, string dummy = null)
    {
        if (dummy != null)
        {
            TimeKeeper.AddTimer(0.2f).OnTimerEnd += () => action(dummyResponse(dummy));
            _request.Dispose();
        }
        else
        {
            _request.SendWebRequest().completed += op =>
            {
               
                if (_request.result != UnityWebRequest.Result.Success)
                {
                    Debug.LogError(_request.error);
                    Debug.LogError(_request.downloadHandler.text);
                }
                else
                {
                    string text = _request.downloadHandler.text;
                    action(text);

                }
                _request.Dispose();
            };
        }

    }

 public class APIAction
    {
        public Action<Root>? Response;
    }

Maybe the issue is caused by UploadHandler that is automatically assigned by Post()? With your current setup you may just create UnityWebRequest via new and assing POST method.

1 Like

Yes! Thank you very much. I added a _request.UploadHandler.Dispose() and the same for the download handler, and it is fixed.

Sidenote, is there a way to mark a solution?

That’s not ideal. Given your original code, create UnityWebRequest using operator new and pass the handlers parameters:
https://docs.unity3d.com/6000.0/Documentation/ScriptReference/Networking.UnityWebRequest-ctor.html
Your current code creates an additional upload handler and throws it away immediately. Better to not create it at all.

Also, the properties for disposing the handlers are true by default, you can save a couple of lines.