Background Memory Error "-403"

I don't know of this error is generic Background Process memory limitations, or specifically related to a WebGet. But using too much memory throws this error.

I had gotten this error before, and i reduced the code and associated memory footprint in the two "background" classes. The main class that extends AppBase, and the webget class that extends ServiceDelegate. That worked.

But it happened again. This may be obvious to most of you. And I know this isn't good behavior. But I created a 1200 element global array in a completely different source file. Turns out all globals are also instantiated in the background. BOOM. -403 error in my WebGet processing. That array didn't have to be global, so sticking it in the module solved the issue.

Just FYI in case someday someone searches for this.

Dave

  • If you're serious about posting this for future forum searchers, it might help to clarify some terms and details in your description of what's actually happening. In the process you might answer your own question ("I don't know of this error is generic Background Process memory limitations, or specifically related to a WebGet").

    TL;DR -403 is an error returned (not thrown) by Communications.makeWebRequest (and other functions named make*Request), which indicates that the process ran out of memory while processing the network response. The process will have a memory spike at this point, as the network response (e.g. JSON) and equivalent Monkey C data structure (e.g. dictionary) will have to exist at the same time. Clearly this error can happen in either the foreground or background, but if you're seeing it in the background, it's because you called makeWebRequest in the background and because background processes usually have less memory than foreground processes.

    Background Memory Error "-403"

    I don't know of this error is generic Background Process memory limitations, or specifically related to a WebGet. But using too much memory throws this error.

    - There's no such thing as a "WebGet" in Connect IQ. Try searching for "connect iq webget" and see how many relevant results you get (they're all related to widgets bc google thinks "webget" is a misspelling of "widget"). Yes, we know what you're talking about, but that wouldn't exactly help future Connect IQ noobs.

    - What you're talking about is likely Communications.makeWebRequest (or one of the similar functions, such as makeImageRequest.) Whatever function you are talking about, it would've been very helpful to put that somewhere in your post. Y'know, for the future forum searchers and browsers

    - A better post title might be: "makeWebRequest returns -403 (NETWORK_RESPONSE_OUT_OF_MEMORY) in background process" or "How to avoid running out of memory when calling makeWebRequest in background"

    - -403 isn't an error that's randomly "thrown" when you use too much memory. -403 is a numerical result code that's returned by makeWebRequest (and similar make*Request functions.) makeWebRequest returns a Number, and non-positive values indicate an error returned by CIQ (as opposed to an error returned by the web server.) Notably, -403 is the value of the NETWORK_RESPONSE_OUT_OF_MEMORY enum, which is documented as "Ran out of memory processing network response."

    - It's misleading and confusing to say "using too much memory throws this error" because it obscures the fact that -403 is returned from a specific function - makeWebRequest (or a similar function) - as opposed to an exception being thrown by some unknown function, under some unspecified circumstances. (Note that javascript actually has the concept of throwing an error, so your incorrect use of "throws this error" might be extra confusing for anyone who's familiar with javascript.)

    - Once it's clarified that -403 is returned from makeWebRequest, that should answer your question:

    Q: "I don't know of this error is generic Background Process memory limitations, or specifically related to a WebGet."

    A: It's related to makeWebRequest (and similar functions) running out of memory while processing the network response. (e.g. converting a JSON response to a dictionary.) Clearly "-403" won't be "thrown" by a background process because it ran out of memory at some random point in time while it was doing some unknown thing, so it's not a generic background process limitation or error.

    In your case, obviously you're getting the error in the background because:

    - you're calling makeWebRequest in the background, and the error is makeWebRequest error

    - the background process typically has less available memory than the foreground process (so you're less likely to see this type of error when you call makeWebRequest in the foreground)

    - as you said, you had wasted a significant amount of memory by defining global variables that didn't need to be in the background

    There's nothing magical or special about the background process with respect to makeWebRequest except for the fact that typically less memory is available, and the fact that you're calling makeWebRequest in the background in the first place. Even in cases where the foreground and background memory is equal (e.g. a data field on an fr935), the background process may require more free memory the foreground app if you're calling makeWebRequest in the background, in order to handle the memory spike when handling the network response (e.g. for JSON, at one point both the actual JSON response and the equivalent Monkey C dictionary will have to exist at the same time.)

    - "the module": we can't see your source code, so we can only guess what you mean by "the module". I guess it's a module in your application?

    It's also worth noting that if you had explicitly used the :background annotation in your app, this situation shouldn't have happened. When that annotation is used, then only things which are explicitly annotated with :background are included in the background process. Anything which isn't explicitly annotated with :background should be excluded from the background process. And surely you wouldn't have annotated your global variables with ":background", right? So actually it's not super clear what has happened here with respect to the :background annotation and the global variables:

    1) Did you not use the background annotation at all? In that case, the entire app would be loaded into the background (as the compiler warning says). But in that case, not sure how moving the global arrays to "the module" would help (since the module would still presumably be in the background), unless you also changed so your code so the arrays are only initialized for the foreground process. (Which ofc could've been accomplished without moving them to a separate module, which would mean it wasn't actually the act of moving them to  "the module" which fixed the problem)

    2) Did you use the background annotation somewhere in your app, but not on the global arrays? In this case, did the global arrays get implicitly added to the background app? That seems like it would be a bug worth reporting, or behavior worth documenting

    3) Did you actually use the background annotation on the global arrays? This seems like the most unlikely scenario, based on what you posted.

  • thx for the detail for future readers :-) no I didn't add (:background) annotation to my globals, but that triggered the abort with -403. I simply moved that one global inside a module and the error went away and all worked correctly both in the sim and on the device.

  • Globals are always included in the background as are class variables in AppBase.  For globals, they are a copy of what's in the main app when the background starts and are not the same physical memory. so if the background changes a global, the main app doesn't see the change.

  • Globals are always included in the background

    If that's the case, it should be documented. What you said has been mentioned in the forums before, but I don't think important information like that should be buried in the forums.

    Currently the documentation implies that if you use the :background annotation, anything which is not annotated with :background should not be included in the :background process. (I'm ignoring the edge case where the dev uses :background, but not on the app entry point / appbase-derived class, and the compiler implicitly adds it to the background process, with a warning.)

    no I didn't add (:background) annotation to my globals, but that triggered the abort with -403. I simply moved that one global inside a module and the error went away and all worked correctly both in the sim and on the device.

    Soooo, I assume you *did* use the background annotation *somewhere*, right? Otherwise your entire app would be loaded into the background process regardless?

    If you did use the background annotation (say, on your appbase-derived class), then combined with what jim_m_58 said, it would explain everything that you saw.

    So the real lesson here is that globals are always included in the background

  • FlowState, Maybe you should have written something with a background service in the last 7+ years,  as there are things that are very obvious if you do.

    See https://forums.garmin.com/developer/connect-iq/f/discussion/5156/1hz-watch-faces---q-a

  • FlowState, Maybe you should have written something with a background service in the last 7+ years,  as there are things that are very obvious if you do.

    I never claimed to know everything about CIQ or to have developed every single kind of app.

    Even if I personally know about some quirks in Connect IQ or Monkey C that others may not, I think such quirks should be documented.

    If it was obvious to everyone else, this topic would not exist. OP has been around for years as well. Of course something like "globals are always included in the background process" are "obvious" once you've observed it for yourself or read it in the forums. That doesn't mean they're obvious or intuitive from the get-go.

    Sorry, I don't think forum knowledge or personal experience is a substitute for good documentation. There are still broken links to the old forums on CIQ blog posts (you should know, since you wrote some of them), due to the changeover from years ago, and some content from the old forums was lost forever (like code snippets, links and images), so clearly it's not a given that forum knowledge will persist forever. And even if knowledge is in the forums, it's not a given that it's easy to find.

    And I don't understand why you would want to discourage people from opening bug reports. I can't force Garmin to act on every bug report, and nor would I want to, but that's not gonna stop me from posting them. Speaking of the distant past, you used to enthusiastically report CIQ bugs (even when it comes to debatable things like whether certain behavior is "obvious" or intuitive) but at some point you switched to discouraging bugs and feature requests whenever possible.

    Are you gonna be around on the forums forever? Will you answer every single question from every single dev? Will every dev necessarily want to come here and ask questions? In the past, newer devs have expressed a desire to use other communication channels like discord or reddit, and every single time you said that they're wrong for wanting to use something other than the forums.

    You often type blatantly incorrect things about subjects that you are not 100% familiar with (but you think you are), like Windows, time zones, open source, etc, so I wouldn't go throwing stones. You also regularly type certain things about CIQ which sound correct but which are wrong or unhelpful in subtle ways. e.g.

    - You said temperature values returned by the API can be numbers or floats but it's no problem if you convert from Celsius to Fahrenheit (as the division and subsequent rounding/truncation will work equally well with numbers and floats if you do it right). While this isn't wrong, it's kind of useless advice for anyone who also wants to display Celsius.

    - You've said multiple times that devs can tell if an "app was launched from a glance" using DeviceSettings.isGlanceModeEnabled. No, they can't (not in general). At best, isGlanceModeEnabled can tell you if an app was *not* launched as a full-screen widget. Even if isGlanceModeEnabled is true, on CIQ 4+ devices, device apps can be launched either from a glance (if a glance view is provided) or from the app list, and isGlanceModeEnabled provides no information to distinguish between the two cases. (Indeed isGlanceModeEnabled should always be true on CIQ 4+ devices, as you can no longer disable glances on those devices.)

    The only case where isGlanceModeEnabled can truly tell you if an app was launched from a glance is for widgets on older pre-CIQ 4 devices which don't support super apps. But you never qualify your statement with that fact.

    - Then there's the time you said that Garmin "System Levels" may be confusing to some, but you understand them. Then you proceeded to misunderstand the definition of System 6. Oh and more recently you said that a certain device is not in System 6 when it actually is, bc you apparently forgot that System 6 includes CIQ 3.4 devices as well as CIQ 4.2 devices (too bad it's not documented, eh). You're the guy who understands everything tho. Nothing needs to be documented or explained by Garmin because you're always here to explain it to everyone else. Nothing ever needs to be fixed or improved, either, because it's all good enough for you.

    - Then there's all the times you misread or misunderstand the OP (or comments that you're replying to) or just don't bother to read what you're replying to in the first place.

    - Then there's the time I reported a bug where the original enduro device's simulator.json incorrectly had a value of true for (glance) liveUpdates when it should be false, and you completely misunderstood what I said, condescendingly repeating back to me half of what I posted in the OP and explaining what glances are (as if it wasn't clear that I already knew that). Someone from Garmin confirmed it was a bug and promised to fix it (somehow they were able to understand my post). Years went by and it wasn't fixed. I responded to the same thread saying it wasn't fixed, and you condescendingly told me that it's not important and I should just edit simulator.json by hand. To Garmin's credit, they finally fixed the bug.

    So for some reason, even when Garmin agrees something is a bug, you don't like it when bugs are reported. And if bugs aren't fixed for years, you don't like it when someone tries to remind Garmin about them. Just really hard to understand. You don't want to see improvements in Garmin devices or CIQ?

    At least I can admit I don't know certain things, and at least I can admit I was wrong when new information is presented to me.

  • You sure do get testy when others do what they can to support other developers, based on actual experience!

  • That is the real lesson and the point of my OP.

  • LOL Yeah I found it entertaining. Glad I was able to teach him something.