How should I detect a misconfigured UrlTemplateImageryProvider?

We provide an interface for users to configure their own baselayer, specifying which provider class to use and giving a provider base URL. Sometimes, they enter a bad URL or have a problem with the service endpoint (misconfigured URL, bad cert, etc). When this happens, I'd like a reliable way to catch the error as early as possible and give some useful feedback that allows them to correct it.

The best feedback I think I can give is to offer them a clickable link to a page that should work, based on the provider base URL. I can probably figure that out for the commonly-used subset of provider classes (ArcGIS, WMS, etc) but my problem is determining that there's an issue in the first place. ImageryProvider offers `errorEvent` but this fires every time a tile fails to load for any reason -- some perfectly healthy services fail to load a tile here and there, either due to server issues or maybe because a particular LOD isn't available.

That leaves `readyPromise`, which is supposed to resolve when a provider is "ready to use", but also will reject when the provider can't be used due to some failure in setup. This is just what I need, but as far as I can tell it only actually rejects for services like ArcGIS or Bing Maps, where initializing the provider triggers a metadata request. A number of other common providers, like WMS or the TileSet provider used for Natural Earth, are based on URLTemplateImageryProvider and never reject the `readyPromise`, because they either don't request metadata at all, or ignore metadata failure and use some default configuration.

So, I need a reliable way to tell when a misconfigured provider is just never going to work, ideally as soon as the user gives me a base URL, that will fire even if this particular provider type doesn't need to make a successful metadata request to function properly. Is this a solved problem? If not, would it be appropriate to modify how these providers work to expose some kind of event for "this will never work as currently configured"?

Best regards,
James

I've been working on this. What I have right now:

        // Hook the event that fires when a tile is requested and fails to load
        const cb = (err) => {
            notifyFailure(provider);
            // Unhook ourselves after the first error
            provider.errorEvent.removeEventListener(cb);
        };

        // Just because this resolves doesn't guarantee that the provider will actually
        // work; if it rejects, the provider definitely won't ever work.
        provider.readyPromise.then(
            () => {
                // Fire our event handler if a tile fails
                provider.errorEvent.addEventListener(cb);
                // Request the first tile (0/0/0) and unhook our failure listener
                // if it loads successfully
                provider.requestImage(0,0,0).then(resp => provider.errorEvent.removeEventListener(cb));
            }, err => {
                // If we failed initialization, tell the user
                notifyFailure(provider);
            }
        );

Basically, notify the user of failure if either the readyPromise rejects (indicating a problem with provider initialization), or if the first tile requested fails. By unhooking the error callback when we succeed at loading a tile, we ensure that later sporadic, non-fatal server errors don't bug the user with spurious notifications.

There's more moving parts here than I'd like, but it's simple enough and seems to work for now. I'd welcome suggestions for improvement.

-J

Hi J,

I believe the readyPromise should reject in this case. We just opened a similar issue [#6242], I’ve updated it with this report. If you can contribute a fix, that would be greatly appreciated.

Thanks,

Gabby