Twitch Bot C# -- runtime errors I'm not sure how to deal with

First time poster over here!

I’ve recently started coding a Twitch Chat Bot, and it’s going pretty well except for a few runtime errors I can’t seem to figure out. I haven’t been keeping any repository of my code (stupid) so I can’t go back and see when they started.

I’ve not had any real experience with networking code until now, so these may be silly and obvious but I haven’t been able to figure them out on my own.

I currently have 3 runtimes I know of. 2 of which are more problematic. The 1st only happens on startup occasionally.

The two most problematic (equally so) are the following, which I’ll link a screenshot to what I get when the runtime occurs, as well as show the code I THINK it’s connected to.

https://pasteboard.co/iX6kmL722.png <-- Runtime #1
https://pasteboard.co/iX7vrNydT.png <— Runtime #2

These runtimes take between 3-15 minutes to hit. (Probably due to my timers, I can shorten them for debugging)
but I’m not able to be reproduce them in a controlled way.

Here is specific code I think may be helpful for RUNTIME #1: ( https://pasteboard.co/iX6kmL722.png )

    private void getMessage() //Receive Messages 
    {
        g_ServerStream = g_IRC.tcpClient.GetStream();

        //Not sure what the following does exactly, only that it works.
        int buffsize = 0;
        byte[] inStream = new byte[10025];
        buffsize = g_IRC.tcpClient.ReceiveBufferSize;

        while(true)
        {
            try
            {
                g_ReadData = g_IRC.readMessage();
                chatUpdate();
            }
            catch(Exception exception)
            {                    
                //Nothing
            }
        }
    }

In that code, g_ReadData is being set to the return of my readMessage() from IRC.
I’d assume the return of readMessage() would only be null if g_IRC was null.
However it’s only caught later on in my chatUpdate() loop, probably because I used a try/catch
Not sure whats going on with this one honestly.

What I think is relevant for RUNTIME #2: (https://pasteboard.co/iX7vrNydT.png)

    private void ViewerListUpdate()
    {
        activeChatUsersListBox.Items.Clear(); //Purge old viewer data
        Chatters AllChatters = ChatClient.GetChatters(g_Channel);
        int numChatters = ChatClient.GetChatterCount(g_Channel);
        activeChatViewersLabel.Text = "Active Chat Users : " + numChatters.ToString();
        activeChatUsersListBox.Text += "Retrieving viewer list...";

        //Get all Admins
        foreach(string admin in AllChatters.Admins)
        {
            activeChatUsersListBox.Items.Add(admin + Environment.NewLine);
            g_activeMods.Add(admin);
        }
        //Get all Twitch Staff
        foreach (string staff in AllChatters.Staff)
        {
            activeChatUsersListBox.Items.Add(staff + Environment.NewLine);
            g_activeMods.Add(staff);
        }
        //Get all global moderators
        foreach (string globalmod in AllChatters.GlobalMods)
        {
            activeChatUsersListBox.Items.Add(globalmod + Environment.NewLine);
            g_activeMods.Add(globalmod);
        }
        //Get all moderators
        foreach (string moderator in AllChatters.Moderators)
        {
            activeChatUsersListBox.Items.Add(moderator + Environment.NewLine);
            g_activeMods.Add(moderator);
        }
        //Get all viewers
        foreach (string viewer in AllChatters.Viewers)
        {
            activeChatUsersListBox.Items.Add(viewer + Environment.NewLine);
        }
        eventsBox.Text = eventsBox.Text + DateTime.Now.ToString("HH:mm:ss ", System.Globalization.DateTimeFormatInfo.InvariantInfo) + ": Viewer list updated!" + Environment.NewLine;
    }

This is where the next runtime occurs, this gives me a lot less information that I can make sense of.
It throws:

System.IndexOutOfRangeException: ‘index was outside the bounds of the array.’

However… I am not using an array here that I know of… Also I’m not sure what would change when running this code later as opposed to when I first run the program.
I update the viewer list on launch, and then every 5 minutes on a timer that simple calls the function above.
I assume it works the first time on launch, then the 2nd time. By the 3rd I think it usually.

Lastly the least problematic one.

https://pasteboard.co/wZSoKlrW.png -> RUNTIME #3

As soon as I start my program it’ll occasionally get stuck here, I assume something with the port/IP (which are correct I believe, them being: irc.chat.twitch.tv" as IP and 6667 as the Port.)

relevant code: (simply what is in the screenshot, as I’m not sure where else it could be)

    public IRCClient(string ip, int port, string userName, string password)
    {
        tcpClient = new TcpClient(ip, port);
        inputStream = new StreamReader(tcpClient.GetStream());
        outputStream = new StreamWriter(tcpClient.GetStream());

        outputStream.WriteLine("PASS " + password);
        outputStream.WriteLine("NICK " + userName);
        outputStream.WriteLine("USER " + userName + " 8 * :" + userName); //Based on Twitch documentation
        //Permission Request for checking viewerlist etc...
        outputStream.WriteLine("CAP REQ :twitch.tv/membership");
        outputStream.WriteLine("CAP REQ :twitch.tv/commands");
        outputStream.Flush();
    }

This one I don’t understand at all, it gives System.Net.Sockets.SocketException: ‘This is usually a temporary error during hostname resolution and means that the local server did not receive a response from the authoritative server’

I assume this means when I started it, it tried to connect to the twitch server failed.
If I start it up again it’ll usually connect in the next 1-2 tries.
Is there a more reliable way to do this? or am I simply doing something wrong?

Hopefully some of you more brilliant coders than I can spot something I can investigate…
Cheers! :slight_smile:

C# isn’t my native language, but some general notes:

I do not know what g_IRC.readMessage() looks like, but it is returning a null value. But, your object is being assigned null rather than a String (I assume String). Check to see what g_IRC.readMessage() is providing, put a null check where you use that g_readData later. Your assumption is possibly incorrect, if g_IRC was null, then it would throw an error trying to access a member of a null object. I would look into how readMessage() works - it might even valid that it returns null and you should account for that.

System.IndexOutOfRangeException: you are walking objects in a foreach, which basically makes them arrays.

I am not familiar with the C# implementation of sockets, but I would put a try { } catch { } style block around that and make sure that an error isn’t occurring.

Sorry these are vague answers, like I said, C# is not my first language.

Cheers

1 Like

Even vague answers are helpful to me right now!

As for the foreach, that makes a lot of sense. I didn’t think of it that way, now I have a bit more to work off, of there.

I’ll try to do a try/catch around that section at start up, maybe google will have some ideas should I find something.

Edit:

I actually forgot I created that IRC bit (it’s early for me LOL) readMessage is NOT able to return a null value.
This is how I wrote that…

    public string readMessage()
    {
        string message = ""; //failsafe, so we don't return nothing.
        message = inputStream.ReadLine();
        return message;
    }

I put in a failsafe specifically to avoid getting a null value.
then I access inputStream.ReadLine() which actually gets the message from chat.

Of course now that I’ve posted this, I’ve been running the program since this was posted give or take a few minutes and it’s been running without a hiccup… :disappointed_relieved: Currently at 46 minutes …
Usually it crashes out in the first 10-15 minutes…

I’m wondering now, could these issues have been caused by stopping and starting the program often over a few hours when testing things? Maybe Twitch doesn’t like that I am connecting/disconnecting so frequently?
it’s very odd…

First of all, I’d recommend using an existing IRC framework instead of writing your own. I’m using a modified version of Thresher IRC, which I optimized for Twitch’s IRC. That way you don’t have to deal with exceptions originating from IRC itself.

ReadLine() CAN return null though. Also, it doesn’t matter that you assign an empty string before calling ReadLine() because it gets overwritten.

The documentation says

Return Value
Type: System.String
The next line from the input stream, or null if the end of the input stream is reached.

you could do something like that

string line = null;
while ((line = _reader.ReadLine()) != null)
{
	try
	{
		// Parse line
	}
	catch (Exception e)
	{
		// Do something here
	}
}

And since this is your own IRC implementation, are you responding to PING properly?

1 Like

Yeah it was probably isn’t the greatest idea to start with writing my own haha.
I think I’ll take a look at some open source ones if I run into much more trouble with mine!

That aside,you’re definitely correct. That line does nothing for me face palm

As for the PING response, I literally was about to post back here saying I found that!
I wrote out the function for responding to pings, but never actually used it later when in my chatUpdate() loop. :laughing:

Had I not figured it out though, you mentioning that would have made me actually look more closely at that!
All I had to add was the following in my chatUpdate()

            if (g_ReadData.Contains("PING"))
            {
                g_IRC.pingResponse();
            }

Now following off that, the code excerpt you wrote would definitely fix it the g_ReadData problem.
However, I think what was happening with g_ReadData being null is because I lost connection to Twitch because I wasn’t responding to their pings, because this would only happen 10-15 minutes when running.

I’m still going to put in that null check for added safety measure, since it still can return Null (thank you for finding that).
But I think that the g_ReadData runtime is now fixed!

Now the only other problematic one left is System.IndexOutOfRangeException runtime…
That could also have been tied to the ping response thing… Cause if I’m no longer connected how can I check who is in chat. Hopefully that’ll have disappeared as well.

IndexOutOfRangeException is most commonly thrown when attempting to access an index greater than or equal to the length of an array or list, or below 0.

int[] numbers = new int[] { 0, 1, 3 };
Console.WriteLine(numbers[2]); // 3
Console.WriteLine(numbers[3]); // IndexOutOfRangeException

It could be a for loop or an attempt to access the first element in an empty array (emptyarray[0] also throws).

foreach should not be able to throw this exception as it does not work by index (it has a different exception for collection length changing while looping)

1 Like

Thanks for letting me know foreach can’t throw that, I’ll keep that in mind for the future! I haven’t actually come across that runtime again as of yet… I think it may have been me not responding to pings that caused it.

As for the array thing, yep that is correct! That is definitely where it is most common!
it was just odd to me because there was no array being used in that particular section of code!
So no idea what array it was talking about still who knows LOL, but it seems to have disappeared for moment :slight_smile:

Also if anybody has any idea of what to do with the first 3rd runtime error, when I start the program and it isn’t able to connect to twitch with the TcpClient then I’d be grateful. I’ve still not been able to figure anything out for that in my testing.

For your third issue, because it’s a resolution error and I was unable to reproduce it using your code, I’m fairly certain it’s a network environment issue, and not an issue with the code you have.

1 Like

@swiftyspiffy Thanks so much for testing that!

That’s very odd, what kind of issue would cause that? Also by network environment I assume you mean my local network, router/modem etc… included? (I have very little experience with networking in code, let alone how an environment can affect it).

Also not sure if at all related, but when I signed up my Twitch Bot for a application ID, I had to enter a a redirect URI which it says under the field that if testing locally to enter “http://localhost”. I assume this is used for logging into a twitch account through your application though, (which I don’t use). Again probably not related but it came to mind so figured I’d mention it.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.