error -300

Hi,

all of sudden my app started to give errors (300, NETWORK_REQUEST_TIMED_OUT) on the following code:

 function callURL(url) {
  // Log url
     Log(url);
  
  // Make the request
        Comm.makeWebRequest(
            url,
            {
            },
            {
                "Content-Type" => Comm.REQUEST_CONTENT_TYPE_URL_ENCODED
            },
             method(:onReceive)
      ); 
    }
The errors however only occur on the watch (i own a forerunner 630, but i also have users reporting the same error on other devices (like vivoactive music 3) and not in the simluator. 
It also does not appear to be a timeout, since the error comes directly after the request was done.
I use exactly the same function in another app, and there it works fine, also on my watch.
anyone, since i have complaining users and i have no clue how to fix, Please help! Does anyone know how to fix? or other possible causes then network timeout?
Kr Arnold
  • I know that link and this explains why HTTP doesn't work for apple devices. 

    i think this is a different cause, because the expected behaviour would then be error -1001 (SECURE_CONNECTION_REQUIRED)

    i capture this error so i can give a friendly error.

    i found a workaround: rollback to garmin connect 3.19 on the handset. 

    Either case it's a a bug in GCM 3.20.

    - some error causing the http requests giving a timeout in 3.20

    - or it is expected behaviour, but then the correct error code should be returned, so a friendly message can be given to the user or a programmer right away knows why it fails.

  • I'm pretty sure you'll only see the -1001 in the sim, as for a while, HTTP could be used on the device (android at least), and it was a way of just warning you about it in the sim.  In the sim you could then uncheck "use device https restrictions" and test.

  • I'm also seeing quite a few -300 errors across all device / GCM OS combinations. My code retries 3 times, and I'm seeing the retries occur *immediately* after each other, not enough for the network to really have timed out.

  • @FlowState, indeed, switching to Let's Encrypt certificate has cleared the "Network Timeout -300" error, the widget is now working correctly.

    It would be nice to:

    1) have a more descriptive error message for security-related events ("network timeout" is not pointing to the root cause)

    2) have means to accept self-signed certificates, if the user wishes.

  • But why do we have problems with simple HTTP website.... sometime we do not want to bother with HTTPS.... I mean for example, I made a small webpage providing info about my current solar panels power, air conditionning and water heater status etc...  but it is not at all critical info.

    I don't care to add any security to such info. I just want to see it easily on my watch, that is all.

    So of course, Garmin can check if an https website is correctly signed if they want, but let us use normal http website if we want to !

    I bought this Garmin watch because it has long lasting battery and also because I was able to develop my own widget if I want to. And now, I cannot use my widget anymore. The problem (as said above by Akamming) comes with the latest Garmin Connect version. So Garmin please solve this as soon as possible and publish a new GCM version. Thanks !

  • cool, glad it works for you now! I agree that a network timeout error doesn't seem ideal here. I think Apple's App Transport Security is pretty strict, and from what I've seen, the only way people are using self-signed certs with ATS is to actually add the issuing authority as trusted to your devices, which is obviously not an option for any apps that aren't just for personal / internal use. Apps are allowed to have specific (not blanket) exceptions, but they're fixed at submission time and require explanation, so it wouldn't work for Garmin Connect Mobile making requests on behalf of 3rd-party CIQ developers.

    Note: ironically, I deleted my original response because I thought it was going in the wrong direction. Basically I said that any blanket policy which disallows HTTP in favour of HTTPS would probably also disallow HTTPS with self-signed certs. In a very real sense HTTPS with a self-signed cert is almost worst than HTTP, because you have a false sense of security. Some would say that Let's Encrypt gives ppl a false sense of security, but that's another discussion....

  • the short answer is they force HTTPS to comply with strict Apple security requirements. Android Pie has this policy by default, although devs can opt out.

    It's just the way the world is going. Google and Apple has made a strong push for the web to HTTPS-only, which is better for end users, although it's a pain for devs.

  • I agree with 1157846.  I just changed my "backend": a domoticz installation to SSL by using a combination of ddns  and letsencrypt. Apart from that this is quite a hassle putting on a lot of extra security which i don't require myself (i use it for switching the lights on and off and viewing some sensors. So no damage done is my password is leaked) i also noticed that on my FR630 the widget runs much much slower now it uses SSL.

    I understand that SSL is more safe and i also understand that if the handset device builder no longer allows HTTP, Garmin must follow.

    What i don't understand why it is enforced by Garmin, where it is allowed by Google.

     So please revert this change in GCM 4.20, so i can happy users again for widget again.

  • I'm not able to reproduce this using a fr630 with the following simple test code:

    using Toybox.Application;
    using Toybox.Communications;
    using Toybox.Graphics;
    using Toybox.System;
    using Toybox.WatchUi;
    
    class ImageRequestView extends WatchUi.View
    {
    	hidden var mCode;
    	hidden var mData;
    	
        function initialize() {
            View.initialize();
        }
    
        function onUpdate(dc) {
        	dc.setColor(Graphics.COLOR_WHITE, Graphics.COLOR_BLACK);
        	dc.clear();
    
        	var cx = dc.getWidth() / 2;
        	var cy = dc.getHeight() / 2;
        	
        	if (mData != null) {
        		dc.drawBitmap(cx - mData.getWidth() / 2, cy - mData.getHeight() / 2, mData);
        	}
    
        	
        	dc.setColor(Graphics.COLOR_WHITE, Graphics.COLOR_TRANSPARENT);
        	if (mCode != null) {
    			dc.drawText(cx, cy, Graphics.FONT_NUMBER_HOT, mCode.toString(), Graphics.TEXT_JUSTIFY_CENTER | Graphics.TEXT_JUSTIFY_VCENTER);
    		} else {
        		dc.drawText(cx, cy, Graphics.FONT_LARGE, "Press Enter", Graphics.TEXT_JUSTIFY_CENTER | Graphics.TEXT_JUSTIFY_VCENTER);
        	}
        }
        
        function setResponse(code, data) {
        	mCode = code;
        	mData = data;
        	WatchUi.requestUpdate();
        }
    }
    
    class ImageRequestDelegate extends WatchUi.BehaviorDelegate
    {
    	hidden static const COLORS = [
            0xFF0000,
            0xAA0000,
            0xFF5500,
            0xFFAA00,
            0x00FF00,
            0x00AA00,
            0x00AAFF,
            0x0000FF,
            0xAA00FF,
            0xFF00FF,
        ];
        
        hidden var mColorIndex;
        hidden var mView;
    
        function initialize(view) {
            BehaviorDelegate.initialize();
            mColorIndex = 0;
            mView = view;
        }
    
        function onSelect() {
            var params = {
            	
            };
    
            var options = {
                :dithering => Communications.IMAGE_DITHERING_NONE,
                :palette => [
                	COLORS[mColorIndex]
                ]
            };
    
            var downloadUrl = Lang.format("https://dummyimage.com/$1$x$2$/$3$/$4$.png", [
                100,
                100,
                COLORS[mColorIndex].format("%06X"),
                COLORS[mColorIndex].format("%06X")
            ]);
            
            mColorIndex = (mColorIndex + 1) % COLORS.size();
    
            Communications.makeImageRequest(downloadUrl, params, options, self.method(:onWebResponse));
        }
    
    	function onWebResponse(code, data) {
    		mView.setResponse(code, data);
    	}
    }
    
    class ImageRequestApp extends Application.AppBase {
    
        function initialize() {
            AppBase.initialize();
        }
    
        function getInitialView() {
        	var view = new ImageRequestView();
            return [ view, new ImageRequestDelegate(view) ];
        }
    }
    

    It sounds like this may affect more devices than just the fenix3, but it isn't clear which ones? If you're seeing this issue (with the above test code so I can be confident that I'm not investigating server-side issues), please let me know what device (I have a host of them to test with, just no fenix3).

    Edit: I just tested with a vivoactive3 and see no problems either. I'm using GCM/iOS 4.19.1.1 and 6.20 firmware on the device.
    Edit: I just update to GCM/iOS 4.20.0.14, and I still see no issues.

    At this point I don't know how much I can help without more information. At the bare minimum, it might be helpful if you showed the url and options/parameters used with the image request.