Home > Blockchain >  TypeError: Cannot read properties of undefined (reading '0') discord.js v13
TypeError: Cannot read properties of undefined (reading '0') discord.js v13

Time:02-16

For some dumb reason, I am using Discord.JS v13. And ever since I have been getting these weird errors that I had no idea exists. Every time I run the command it just gives an error and shuts down the bot. I tried adding the try and catch but those dont work for v13 anymore I dont think. Here is my code if you guys can help.

The error is at line 32 btw

const Discord = require('discord.js')
const { MessageEmbed } = require('discord.js')
const https = require('https')
const url = 'https://www.reddit.com/r/catpics/hot/.json?limit=300'
module.exports = {
    name: "cat",
    description: "meow",
     execute(message, args, client) {
        message.reply("I am loading the image, if it does not come up try again later due to errors.")
        https.get(url, (result) => {
            var body = ''
            result.on('data', (chunk) => {
                body  = chunk
            })

            result.on('end', () => {
                var response = JSON.parse(body)
                var index = response.data.children[Math.floor(Math.random() * 99)   1].data

                if (index.post_hint !== 'image') {

                    var text = index.selftext
                    const textembed = new Discord.MessageEmbed()
                        .setTitle("cute")
                        .setColor(9384170)
                        .setDescription(`[${title}](${link})\n\n${text}`)
                        .setURL(`https://reddit.com/${subRedditName}`)

                    message.channel.send({embeds: [textembed]})
                }

                var image = index.preview.image[0].source.url.replace('&', '&')
                var title = index.title
                var link = 'https://reddit.com'   index.permalink
                var subRedditName = index.subreddit_name_prefixed

                if (index.post_hint !== 'image') {
                    const textembed = new Discord.MessageEmbed()
                        .setTitle("cute")
                        .setColor(9384170)
                        .setDescription(`[${title}](${link})\n\n${text}`)
                        .setURL(`https://reddit.com/${subRedditName}`)

                    message.channel.send({embeds: [textembed]})
                }
                console.log(image);
                const imageembed = new Discord.MessageEmbed()
                    .setTitle("cute")
                    .setImage(image)
                    .setColor(9384170)
                    .setDescription(`[${title}](${link})`)
                    .setURL(`https://reddit.com/${subRedditName}`)
                message.channel.send({embeds: [imageembed]})
            }).on('error', function (e) {
                console.log('Got an error: ', e)
            })
        })

     }
}

Output:

TypeError: Cannot read properties of undefined (reading '0')

CodePudding user response:

Since I'm guessing you have no background on programmation, I'm gonna go over every part of the code you probably copy-pasted from an example and/or adapted to your needs and try to explain in-depth what behavior you should adopt when any error comes. I'll stop once we reach the line of the error, line 32.

Keep in mind that it is not the place but I'm gonna do it as a one-time thing. The appropriate place would be Stack Exchange's Code Review.

First, given the url and the presence of https module, I assume you try to retrieve informations about pictures of cats from Reddit.

Let's dive directly where there's code to discuss. The result.on('end') function will be executed when there is no more body to parse, but I think you got that.

Then, you try to retrieve data about a particular image, chosen at random:

var index = response.data.children[Math.floor(Math.random() * 99)   1].data

Two things from here:

  • Math.random() only returns a number between 0 and 1, making this whole line chosing a number between 1 and 100. You then miss the opportunity to chose the element 0, since Arrays in JS are zero-based indexed. Also, you can reduce the limit in your Reddit URL from 300 to 100.
  • You assume 2 things: that children is indeed a key of the response Reddit sent you back, AND that the children array goes up to 100 elements.

What happens if children array has only, say 15 elements (if it exists at all)? You will have another error. I'll leave it to you to come up with a solution to check both things.

There:

var image = index.preview.image[0].source.url.replace('&', '&')

you once again assume that preview, image (as an array), source, and url exist.

Now I've gone ahead and copy-pasted the result of the URL https://www.reddit.com/r/catpics/hot/.json?limit=100 in a JSON Beautifier, and it happens that the preview you're asking on line 32 exists, however, image don't.

You only forgot an s, since images exists under preview.

In fact, your error comes down to two things:

  1. The variable index might be undefined because you might try to access response.data.children array with an unreachable index (e.g response.data.children has only 15 elements and your Math.random gives you 55)
  2. image field doesn't exist in preview, only images do.

Finally, to illustrate the TypeError you got, it is like asking someone to read you a completely blank paper, or giving an essay to a blind person and telling him to read it for you.

Either way, before asking a question on here, you should try a little harder. You could have figured it out yourself if you tried to log in between each line until narrowing down the error.

Also, if these are weird errors that I had no idea exists, then you're not really ready to code yet. I get these TypeError a half-dozen times a day if not more. That may sound harsh but you can't come and ask for help for any minor inconvenience you come across, or else you won't learn anything. Not to mention you didn't post a minimum reproducible example.

With all that said, I stay available in the comments if the two things I mentioned you should fix don't solve the issue.


Following the comments on this answer, I'll add more details. I'll go through how to resolve the issue as well, so OP can apply similar thinking and procedures for other problems.

If you go on this page, which is the URL present on your code, only not in JSON form, you will see that there are posts that you want to exclude. Typically, I don't think the posts from TrendingBot are interesting, so you can just exclude them. That is why you were having /r/catpics enters TOP 5000 subreddits. Anything that has index.author === 'TrendingBot' is no bueno.

For the others matters, you can inspect keys and values via a JSON beautifier (that I linked above).

Looking at the JSON beautified myself, I don't think you're searching for the right key regarding the image. The image you probably want to display is the image under the index.url key, which is the image of the actual post. I really don't think preview is what you should be searching for.

Finally, for the link, again, I don't think you're searching for the right key. I think you should grab index.permalink instead of index.subreddit_name_prefixed.

Your final message should look something like this:

const image = index.url.replace('&', '&');
const title = index.title;
const link = 'https://reddit.com'   index.permalink;
const subRedditName = index.subreddit_name_prefixed;

const imageembed = new Discord.MessageEmbed()
                    .setTitle("cute")
                    .setImage(image)
                    .setColor(9384170)
                    .setDescription(`[${title}](${link})`)
                    .setURL(link);
  • Related