Error on makeWebRequest returned data

I'm experiencing an error (Failed invoking <symbol>) after a return from makeWebRequest. Is suspect it may be a data typing, but it has me stumped.

Here is the code:

function onReceive(responseCode, data) {
if (responseCode == 200) {
System.println("Request Successful"); // print success


//****** The following println throws "Failed invoking <symbol>"


System.println("bg exit: " + data);
System.println("Exiting background");
Background.exit(data);
} else {
System.println("Response: " + responseCode); // print response code
}
}


function onTemporalEvent() {


Communications.makeWebRequest(
"https://api.darksky.net/forecast/<secret_key>/37.8267,-122.4233",
{ "exclude" => "[hourly,currently,daily,alerts,flags]"
},
{
:headers => { "Content-Type" => Communications.REQUEST_CONTENT_TYPE_URL_ENCODED
},
:responseType => Communications.HTTP_RESPONSE_CONTENT_TYPE_JSON
},
method(:onReceive)


);
}



The line

System.println("bg exit: " + data);

in the onReceive method throws the "Failed invoking <symbol>" error. The return from the server is JSON.

However, the following code (which is from the ConnectIQ WebRequest example and which also returns JSON) works:

function makeRequest() {
notify.invoke("Executing\nRequest");
Comm.makeWebRequest(
"https://jsonplaceholder.typicode.com/todos/115",
{
},
{
"Content-Type" => Comm.REQUEST_CONTENT_TYPE_URL_ENCODED
},
method(:onReceive)
);
}


I thought it might be useful to show the JSON from the two calls:

From the broken darksky call:

{"latitude":37.8267,"longitude":-122.4233,"timezone":"America/Los_Angeles","minutely":{"summary":"Clear for the hour.","icon":"clear-day","data":[{"time":1523576100,"precipIntensity":0,"precipProbability":0},{"time":1523576160,"precipIntensity":0,"precipProbability":0},{"time":1523576220,"precipIntensity":0,"precipProbability":0},{"time":1523576280,"precipIntensity":0,"precipProbability":0},{"time":1523576340,"precipIntensity":0,"precipProbability":0},{"time":1523576400,"precipIntensity":0,"precipProbability":0},{"time":1523576460,"precipIntensity":0.003,"precipIntensityError":0.001,"precipProbability":0.01,"precipType":"rain"},{"time":1523576520,"precipIntensity":0.003,"precipIntensityError":0.001,"precipProbability":0.01,"precipType":"rain"},{"time":1523576580,"precipIntensity":0.003,"precipIntensityError":0.001,"precipProbability":0.02,"precipType":"rain"},{"time":1523576640,"precipIntensity":0.003,"precipIntensityError":0.001,"precipProbability":0.03,"precipType":"rain"},{"time":1523576700,"precipIntensity":0.003,"precipIntensityError":0.001,"precipProbability":0.04,"precipType":"rain"},{"time":1523576760,"precipIntensity":0.003,"precipIntensityError":0.001,"precipProbability":0.05,"precipType":"rain"},{"time":1523576820,"precipIntensity":0.003,"precipIntensityError":0.001,"precipProbability":0.07,"precipType":"rain"},{"time":1523576880,"precipIntensity":0.003,"precipIntensityError":0.001,"precipProbability":0.08,"precipType":"rain"},{"time":1523576940,"precipIntensity":0.003,"precipIntensityError":0.001,"precipProbability":0.09,"precipType":"rain"},{"time":1523577000,"precipIntensity":0.003,"precipIntensityError":0.001,"precipProbability":0.1,"precipType":"rain"},{"time":1523577060,"precipIntensity":0.003,"precipIntensityError":0.001,"precipProbability":0.11,"precipType":"rain"},{"time":1523577120,"precipIntensity":0.003,"precipIntensityError":0.001,"precipProbability":0.12,"precipType":"rain"},{"time":1523577180,"precipIntensity":0.003,"precipIntensityError":0.001,"precipProbability":0.13,"precipType":"rain"},{"time":1523577240,"precipIntensity":0.003,"precipIntensityError":0.001,"precipProbability":0.14,"precipType":"rain"},{"time":1523577300,"precipIntensity":0.003,"precipIntensityError":0.001,"precipProbability":0.14,"precipType":"rain"},{"time":1523577360,"precipIntensity":0.003,"precipIntensityError":0.001,"precipProbability":0.14,"precipType":"rain"},{"time":1523577420,"precipIntensity":0.003,"precipIntensityError":0.001,"precipProbability":0.15,"precipType":"rain"},{"time":1523577480,"precipIntensity":0.003,"precipIntensityError":0.001,"precipProbability":0.15,"precipType":"rain"},{"time":1523577540,"precipIntensity":0.003,"precipIntensityError":0.001,"precipProbability":0.15,"precipType":"rain"},{"time":1523577600,"precipIntensity":0.003,"precipIntensityError":0.001,"precipProbability":0.15,"precipType":"rain"},{"time":1523577660,"precipIntensity":0.003,"precipIntensityError":0.001,"precipProbability":0.14,"precipType":"rain"},{"time":1523577720,"precipIntensity":0.003,"precipIntensityError":0.001,"precipProbability":0.14,"precipType":"rain"},{"time":1523577780,"precipIntensity":0.003,"precipIntensityError":0.001,"precipProbability":0.15,"precipType":"rain"},{"time":1523577840,"precipIntensity":0.003,"precipIntensityError":0.001,"precipProbability":0.15,"precipType":"rain"},{"time":1523577900,"precipIntensity":0.003,"precipIntensityError":0.001,"precipProbability":0.14,"precipType":"rain"},{"time":1523577960,"precipIntensity":0.003,"precipIntensityError":0.001,"precipProbability":0.14,"precipType":"rain"},{"time":1523578020,"precipIntensity":0.003,"precipIntensityError":0.001,"precipProbability":0.14,"precipType":"rain"},{"time":1523578080,"precipIntensity":0.003,"precipIntensityError":0.001,"precipProbability":0.14,"precipType":"rain"},{"time":1523578140,"precipIntensity":0.003,"precipIntensityError":0.001,"precipProbability":0.14,"precipType":"rain"},{"time":1523578200,"precipIntensity":0.003,"precipIntensityError":0.001,"precipProbability":0.14,"precipType":"rain"},{"time":1523578260,"precipIntensity":0.003,"precipIntensityError":0.001,"precipProbability":0.13,"precipType":"rain"},{"time":1523578320,"precipIntensity":0.003,"precipIntensityError":0.001,"precipProbability":0.13,"precipType":"rain"},{"time":1523578380,"precipIntensity":0.003,"precipIntensityError":0.001,"precipProbability":0.13,"precipType":"rain"},{"time":1523578440,"precipIntensity":0.003,"precipIntensityError":0.001,"precipProbability":0.13,"precipType":"rain"},{"time":1523578500,"precipIntensity":0.003,"precipIntensityError":0.001,"precipProbability":0.12,"precipType":"rain"},{"time":1523578560,"precipIntensity":0.003,"precipIntensityError":0.001,"precipProbability":0.12,"precipType":"rain"},{"time":1523578620,"precipIntensity":0.003,"precipIntensityError":0.001,"precipProbability":0.12,"precipType":"rain"},{"time":1523578680,"precipIntensity":0.003,"precipIntensityError":0.001,"precipProbability":0.11,"precipType":"rain"},{"time":1523578740,"precipIntensity":0.003,"precipIntensityError":0.001,"precipProbability":0.12,"precipType":"rain"},{"time":1523578800,"precipIntensity":0.003,"precipIntensityError":0.001,"precipProbability":0.11,"precipType":"rain"},{"time":1523578860,"precipIntensity":0.003,"precipIntensityError":0.001,"precipProbability":0.11,"precipType":"rain"},{"time":1523578920,"precipIntensity":0.003,"precipIntensityError":0.001,"precipProbability":0.11,"precipType":"rain"},{"time":1523578980,"precipIntensity":0.003,"precipIntensityError":0.001,"precipProbability":0.11,"precipType":"rain"},{"time":1523579040,"precipIntensity":0.003,"precipIntensityError":0.001,"precipProbability":0.1,"precipType":"rain"},{"time":1523579100,"precipIntensity":0.003,"precipIntensityError":0.001,"precipProbability":0.1,"precipType":"rain"},{"time":1523579160,"precipIntensity":0.003,"precipIntensityError":0.001,"precipProbability":0.1,"precipType":"rain"},{"time":1523579220,"precipIntensity":0.003,"precipIntensityError":0.001,"precipProbability":0.1,"precipType":"rain"},{"time":1523579280,"precipIntensity":0.003,"precipIntensityError":0.001,"precipProbability":0.1,"precipType":"rain"},{"time":1523579340,"precipIntensity":0.003,"precipIntensityError":0.001,"precipProbability":0.09,"precipType":"rain"},{"time":1523579400,"precipIntensity":0.003,"precipIntensityError":0.001,"precipProbability":0.09,"precipType":"rain"},{"time":1523579460,"precipIntensity":0.003,"precipIntensityError":0.001,"precipProbability":0.09,"precipType":"rain"},{"time":1523579520,"precipIntensity":0.003,"precipIntensityError":0.001,"precipProbability":0.09,"precipType":"rain"},{"time":1523579580,"precipIntensity":0.003,"precipIntensityError":0.001,"precipProbability":0.09,"precipType":"rain"},{"time":1523579640,"precipIntensity":0.003,"precipIntensityError":0.001,"precipProbability":0.08,"precipType":"rain"},{"time":1523579700,"precipIntensity":0.003,"precipIntensityError":0.001,"precipProbability":0.08,"precipType":"rain"}]},"offset":-7}

From the working example call: { "userId": 6, "id": 115, "title": "sed et ea eum", "completed": false }

I'm quite certain this is a blind noob problem, but appreciate any help!
  • What do your "using" lines look like? Have you tried commenting out on or both of the printlin calls to see which might be causing it?

    BTW, the way I do things like darksky, is if the response code is 200, I return the payload, and if not, return the response code, and then in onBackgrounddata, I check for instance of Number, so the calling app can display the error if needed.

    When I specify exclude, mine is "minutely,hourly,daily,alerts,flags"

    I don't recall what "currently" does, but you may be getting a large response back and memory in a background process is very tight. Maybe just try changing "currently" to "minutely"
  • Oh, for error codes, I do a bit of checking in the background before I do the makeWebRequest. If phoneConnected is false, or if the lat/lon aren't available, or if the API key isn't 32 characters long, I skip the call, and just return an error.
  • Jim, thanks for the ideas.

    Here's the "using block"

    using Toybox.Background;
    using Toybox.System;
    using Toybox.Communications;

    On returning the response code: that's smart.

    It's definitely failing on the System.println("bg exit: " + data); statement -- which I just don't get. Based on your thoughts, I started to think about the length of the response. I definitely was not getting either of NETWORK_RESPONSE_TOO_LARGE = -402
    NETWORK_RESPONSE_OUT_OF_MEMORY = -403 in the return code. But I replaced the "currently" parameter with "minutely" and sure enough, it works. Is there perhaps some length limit on the var "data" in the println statement? Or perhaps something in the JSON response is confusing the println? The size of the response that includes "minutely" is 7,017 bytes, so, I don't think that should be too big???

    (As an experiment on response size, I removed the "hourly" from the exclude parameters and got the NETWORK_RESPONSE_TOO_LARGE = -402 return code, with a 17KB response size, fwiw.)

    Sadly, what I'm doing is all about "minutely" so I want to figure it out. Still looking.
  • You might not get the -402/-403 depending on where it ran out of memory. At least that was the case in the past. I'd say you're simply trying to get to much data in the background.

    To verify that, move your logic to a widget or watch-app and insure it runs in the foreground process.

    Use "view memory" in the sim and check your peak usages. (keep the widget or app really simple)
  • I ran into this problem yesterday trying to write some test code. I think I know what the problem is, but I haven't had a chance to verify.

    Think for a second about what is happening when you execute the following...

    // assume `data' is a json object (a Monkey C dict with lots of data)
    System.println("bg exit: " + data);


    The order of operations is not necessarily accurate, but here is a high level break down
    • convert `data` to a Lang.String
    • convert "bg exit: " to a Lang.String (if necessary, this could be optimized out)
    • allocate a string that is big enough to hold the two combined strings (the literal and the result of step 1)
    • copy the literal "bg exit: " with the result of the previous step.
    • deallocate the Lang.String allocated in steps 1 and 2
    • print the resulting string.
    Assume that the `data` object is 200 bytes. The temporary stringified version of it is likely going to be at least 200 bytes, and then the combined one is going to be another 200 bytes. That is a lot of memory for such a small bit of code.

    You could easily cut out a bunch of memory by avoiding the string concatentation like so...

    System.print("bg exit :");
    System.println(data);


    If you really need to print it, you can break it up by recursively printing the elements. I wouldn't do it, but if you really need to, that would work.

    Travis
  • Travis,

    That's interesting... and I wondered if something like that was going on. Now that you explain it like that, it makes sense. I too have not had time to verify your assumption, but I did notice that if the returned `data` object was roughly 7kb, the whole routine would frequently work on the first call, but then would fail on every subsequent call. I was able to confirm this with multiple weather API sources. I can see how your explanation could make sense in that when the first call is made, the system/simulator memory is "clean" and all is well. On subsequent calls, the memory is fuller/krufty and it just gets overloaded somewhere down the line (even though it wasn't returning response codes of either -402 or -403.)

    I definitely don't need to print it, so I will probably give it another try (but am concerned that I still may be too close to the response size limit to be reliable.)

    Alternatively, I was able to achieve my result by using a different weather API service: aerisweather.com. For anyone interested, this service is highly customizable and the contents (and therefore size) of the response can be tailored very specifically (and in my case, super tiny). It's a commercial weather feed business, so you'll have to figure out for yourself whether or not the fees make sense (but their developer API service is quite generous on the number of calls you can make each day.)