Script spontaneously... terminating? table.create possibly silently failing

Trying to diagnose my music player and ran into an issue where my script seemingly decides to terminate or silently fail table creation. Not sure if I’m a clown or I’m encountering a real bug. All prints below, except for the prints that create tables as well as the one in the loop, successfully run.

I’ve included the raw code I’m using with irrelevant pieces removed.

function Butler:StopAll(updateInfo: UpdateInfo?)
    print("STOPPING") -- Runs
    -- Below runs successfully
    if not updateInfo then print("THERE WAS NO UPDATEINFO") updateInfo = {} end

    print("FILLED UPDATEINFO") -- Runs

    -- Everything below does not run
    local barfoo: table = {}
    local foobar: table = table.create(MAX_LOADED_TRACKS)
    local promises: table = table.create(MAX_LOADED_TRACKS)
    print(barfoo)
    print(foobar)
    print(promises)
    -- Everything above does not run

    print("CREATED TABLES") -- Runs
    
    for _: string, trackName: string in ipairs(self:GetTracks(true)) do
        print(_, trackName) -- Does not run
    end

    print("DID A FOR LOOP, DID A SNEAKY, CLOSING UP") -- Runs
    
    return Promise.all(promises):catch(function() end)
end

Any ideas as to why this is happening?

3 Likes

I’m having a brain stroke right now because I’ve never seen someone write code in LuaU the way it’s intended
Could you perhaps translate the code back to vanilla Lua for us so that it’s easier to understand

Are you sure the _ key is supposed to be a string type? If so, I would switch to a pairs iterator.

Otherwise, I have no idea what’s going on… maybe MAX_LOADED_TRACKS isn’t a number?

@NOVEIGMA You can ignore all the typechecking, it’d just be the same code. All the colons except for Butler:StopAll, self:GetTracks(true) and :catch are for typechecking purposes so if you just ignore those then it should be okay for you to read. If that doesn’t help I can remove the types.

@goldenstein64 Yes, GetTracks returns an array of names. The for loop is less-so my problem, the main problem is that my tables don’t get created at all and don’t print out either. I would know because I’d see a memory address in a live server but that doesn’t exist in my console.

Raw GetTracks function for reference:

function Butler:GetTracks(playingOnly: boolean?): table
    return Promise.new(function (resolve)
        local query: table = table.create(MAX_LOADED_TRACKS)
        
        for trackName: string, track: SoundtrackInfo in pairs(loadedTracks) do
            if (playingOnly and not (track.Sound.IsPlaying)) then continue end
            table.insert(query, trackName)
        end
        
        resolve(query)
    end):catch(function()
        self:DebugLog("An unexpected issue occurred during GetTracks() which should normally never fail.", "warning")
    end)
end
1 Like

I can’t figure exactly what’s going on, but it seems difficult to figure out what stops it from running. Possibly some weird behavior with table.create that I have not foreseen.

On a trivial note:

for _: string, trackName: string in ipairs(self:GetTracks(true)) do
    print(_, trackName) -- Does not run
end

This looks like a confusion. ipairs only work on arrays, which obviously tells why it doesn’t work as intendedly. If _: string, this looks like a dictionary, but ipairs is for arrays only…

1 Like

I realise the clown moment with my typechecking there: the index in the StopAll for loop would be invalid, it should be (number, string) not (string, string). This would only trip script analysis though and should not be blocking my code from running.

1 Like

Can you try putting the code that doesn’t run in a pcall and seeing if it runs successfully?

local barfoo: table, foobar: table, promises: table
local success: boolean, message: string? = pcall(function()
	barfoo = {}
	foobar = table.create(MAX_LOADED_TRACKS)
	promises = table.create(MAX_LOADED_TRACKS)
end)

print(success, message)

-- maybe comment these out?
print(barfoo)
print(foobar)
print(promises)

The pcall runs successfully, though the tables do not get created.

My confusion is immeasurable.

1 Like

Oh man, I knew it, I had a brain fart. Thanks for the help but I should pay more attention.

First off, the issue does not lie with table.create. I printed the table types and they exist. The real issue actually involves GetTracks. That method is returning a Promise (dictionary), not the array of track names I was hoping it’d return. This is an oversight on my part.

To solve this issue, I used expect to get the exact return values that the Promise resolves with.

MAN.

self:GetTracks(true):expect()

This is the table being passed to the for loop now, so the for loop receives the actual array instead of a Promise (dictionary). :man_facepalming:

As for where those tables went? They were getting created. I’m not going to question why they didn’t send anything to the console though when printed, that’s an anomaly I need to resolve later.

Additional thanks, Operatik, for catching the incorrect typechecking.

2 Likes