In Android: attempt to index upvalue 'stoneImage' (a nil value)

This issue is sporadic. It crashes in the line
stoneImage.x = 100;

Any idea why?

local group = display.newGroup();
local function networkListener(event)
      if (event.isError) then
        print("Network error - download failed");
      elseif (event.phase == "ended") then
        stoneImage = display.newImageRect(
          group,
          event.response.filename, 
          event.response.baseDirectory, 
          100, 100
        );
        stoneImage.x = 100;
        stoneImage.y = 100;
      end
    end

local requestId = network.download(
  url,
  "GET",
  networkListener,
  {progress = true},
  "stone.png", 
  system.TemporaryDirectory
);

The line is failing because the display object does not exist. Normally that’s because the image is missing or the filename is incorrect but given you’re reading those directly from event.response that seems unlikely.
Have you tried printing out event.response.filename and event.response. baseDirectory to make sure they have valid values, and is group definitely accessible in this part of your code?
It’s possible that the event has been received before the image has finished being saved to the Temp directory. I would try wrapping the stoneImage code in a timer.performWithDelay call, to give it time to finish writing the image file to local storage:

local function networkListener(event)
    if (event.isError) then
        print("Network error - download failed");

    elseif (event.phase == "ended") then

        print("networkListener response:")
        print(event.response.filename)
        print(event.response.baseDirectory)
        print(group) --just to check it's not nil
        
        local function drawStoneImage()
            stoneImage = display.newImageRect(
              group,
              event.response.filename, 
              event.response.baseDirectory, 
              100, 100
            );
            stoneImage.x = 100;
            stoneImage.y = 100;
        end

        timer.performWithDelay(100, drawStoneImage)
    end
end
1 Like

Hey alanFlickGames!
Thanks a lot for the prompt reply : )

I was under the impression that when we get the event.phase == "ended", the download of the image is complete and it is successfully saved. Is that not the case?

I understand why adding delay would work, but would it work 100% of the time? It looks like, it’ll reduce the probability of facing this issue rather than solving it entirely.

Is there a condition I could wrap the drawStoneImage function within inside the networkListener? which ensures that the drawStoneImage function is called only after the image is saved successfully.

And lastly, yes group is accessible in that part of the code. I edited the code above to make it clearer.

If I understand this correctly it works with the timer because it is the “next tick”. So the options you have are:

  1. Set the timer as it was mentioned earlier. It should work every time.
  2. Check to make sure the file is there before doing anything with an io call. You might have to put it in a while loop. I don’t think this is a good idea but throwing it out there. The while loop would accomplish the same as number 1.
  3. Use the call back to set a variable and then wait for the next enter frame to load the image. Again probably the same as number 1 but a lot of work.
1 Like