1

As from about Sep 21 2025, a Windows program I developed in Delphi that downloads online OpenStreetMap tiles using Indy's TIdHTTP.Get() method has stopped working, sometimes issuing error messages like EIdIOHandlerPropInvalid "IOHandler value is not valid". What changes in Delphi, the Indy library, or the OpenStreetMap tile URLs could possibly have caused the error? The Delphi program has been working satisfactorily for a long time now.

The error occurs in this code:

MemoryStream.Position:= 0;
IdHTTP1.Get(SourceURL, MemoryStream);

The tile URL format that the program uses is

http://{s}.tile.openstreetmap.org/{z}/{x}/{y} where s='a'

The TIdHTTP component is created and destroyed in the initialization and finalization sections of the unit in which it is declared. The code is as follows:

initialization
  IdHTTP1:= TIdHTTP.Create(nil);
  {$ifdef include_TIdSSLIOHandlerSocketOpenSSL}
  SSLIOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
  SSLIOHandler.SSLOptions.Method := sslvSSLv2;
  SSLIOHandler.SSLOptions.Mode := sslmClient;
  IdHTTP1.IOHandler:= SSLIOHandler;
  {$endif}
  IdHTTP1.HandleRedirects := True;
  Alpha:=  arctan(sinh(Pi));

finalization
  {$ifdef include_TIdSSLIOHandlerSocketOpenSSL}
  SSLIOHandler.Free;
  {$endif}
  IdHTTP1.Free;
end.

The unit is compiled with the directive

{$undef include_TIdSSLIOHandlerSocketOpenSSL}
2
  • 2025-10-21 hasn't occurred yet. Do you mean 2025-09-21? Commented Sep 26 at 11:17
  • Thank you for spotting typo - yes, I meant 2025-09-21! Commented Sep 26 at 11:31

2 Answers 2

2

An EIdIOHandlerPropInvalid error occurs when an https: url is being requested and either:

  • the TIdHTTP.IOHandler is assigned, but is not pointing at an TIdSSLIOHandlerSocketBase-derived object.

  • the TIdHTTP.IOHandler is not assigned, and a default TIdSSLIOHandlerSocketBase-derived object cannot be created (because no such class has been registered with TIdIOHandler.RegisterIOHandler()).

You say that you are compiling your unit with include_TIdSSLIOHandlerSocketOpenSSL undefined, so you are not setting the IOHandler yourself. By default, TIdHTTP will create a default IOHandler if it needs one, and will then hold on to that object for subsequent requests (unless you reassign it).

If you don't assign the IOHandler yourself and the 1st url requested is:

  • http: (as in your case) - the default IOHandler will be a TIdIOHandlerStack (non-SSL/TLS).

  • https: - the default IOHandler will be TIdSSLIOHandlerSocketOpenSSL if IdSSLOpenSSL is in your uses clause.

In your example, if you request an http: url, and it redirects to an https: url, you could get the EIdIOHandlerPropInvalid error.

So, if there is even the slightest possibility that your app could ever request an https: url (explicitly, or through HTTP redirects, etc) then you should make sure an TIdSSLIOHandlerSocketBase-derived IOHandler is always assigned. TIdHTTP will enable/disable SSL/TLS on it on a per-request basis as needed.


When include_TIdSSLIOHandlerSocketOpenSSL is defined, you are creating your TIdSSLIOHandlerSocketOpenSSL object with SSLOptions.Method := sslvSSLv2;, which means it will use only SSL v2.0. Nobody today uses SSL v2.0 anymore as it's long obsolete and no longer secure. This can easily account for the tlsv1 alert protocol version error you get when you change your requested URL to https:.

At a minimum, you should be using TLS v1.0, although most modern servers now require at least TLS v1.1 or v1.2 (and many now support v1.3). You should ignore the SSLOptions.Method property as it's been deprecated for a long time. Use the SSLOptions.SSLVersions property instead, and set it to [sslvTLSv1,sslvTLSv1_1,sslvTLSv1_2] (by default, it is initialized to [sslvTLSv1], which will be addressed in a future Indy release).

Sign up to request clarification or add additional context in comments.

3 Comments

In my similar program, the exception gets raised here: else if not (IOHandler is TIdSSLIOHandlerSocketBase) then begin raise EIdIOHandlerPropInvalid.Create(RSIOHandlerPropInvalid); in TIdCustomHTTP.CheckAndConnect. So in my case IOHandler is assigned, but apparently not derived from TIdSSLIOHandlerSocketBase. Its Classname at the time of the exception is 'TIdIOHandlerStack' which indeed seems not to be derived from TIdSSLIOHandlerSocketBase.
TIdIOHandlerStack is the default non-TLS socket handler. So this goes right back to what I described in my answer. First an http: url must have been requested, creating the default IOHandler, and then after an https: url was requested and failed since a non-TLS IOHandler was present. TIdHTTP is not designed to change IOHandler types dynamically, so you have to make sure to assign a TLS-enabled IOHandler from the beginning if you need to access https: urls
Checking the site's SSL supported protocols using ssllabs.com/ssltest currently shows TLS 1.3 and TLS 1.2 only.
1

{s}.tile.openstreetmap.org is deprecated, tile.openstreetmap.org is the prefered URL now.

OSM is also starting to enforce the requirement for a valid HTTP Referer/User-Agent.

Lastly, bulk downloading basemap tiles is forbidden, and could lead to a ban IP, depending on your usage.

All of this is sourced from the Tile Usage Policy

8 Comments

I tried changing the OSM tile URL. This time the following error is raised: Project OpenStreetMapViewer.exe raised exception class EIdOSSLUnderlyingCryptoError with message 'Error connecting with SSL. error:1409442E:SSL routines:ssl3_read_bytes:tlsv1 alert protocol version'.
Kinda weird, if you're blocked by the foundation, the request should return this : wiki.openstreetmap.org/wiki/Blocked_tiles, and tile.osm.org did'nt change any SSL config since at least a year : cryptcheck.fr/https/tile.openstreetmap.org ; do you have a proxy ?
My computer accesses the Internet via a VPN, but this hasn't interfered with the smooth functioning of my OpenStreetMapViewer program before. Could the VPN be a contributory cause?
@user11935527 "tlsv1 alert protocol version" - By default, TIdSSLIOHandlerSocketOpenSSL enables only TLS 1.0. Try configuring it to use TLS 1.2 instead.
Having taken a quick look at the TileUsagePolicy, I guess that my program doesn't comply with the requirements for licence attribution, valid HTTP User-Agent, HTTP Referer, caching tile locally. I don't recall these requirements being in existence when I developed the program. But given that my program is used only by me relatively lightly, I don't think that it abuses the OSM server with excessive traffic. Are there any examples of code for providing the OSM server the additional info on licence attribution, HTTP User-Agent, HTTP Referer, etc that is currently required?
I maintain a similar program, also using Delphi and TIdHTTP, and remember the requirements being the same at least 10 years ago. I just tried it and got the same "IOHandler value is not valid error" that you get. I guess some people will have some very urgent support requests for me on Monday...
If you use a mix of http: and https: urls then simply assign a TIdSSLIOHandlerSocketOpenSSL (or other SSLIOHandler component) explicitly to the TIdHTTP.IOHandler property before making any requests, don't rely on TIdHTTP creating its own IOHandler instance implicitly, and then you won't get that error anymore.
The problem in my case was indeed the redirection of the http request to a https url, just as @RemyLebau suggested. I switched to https + a TIdSSLIOHandlerSocketOpenSSL handler now and everything works again. It is even much faster, probably because the redirection added overhead.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.