Hi,
I came across an interesting edge case with a TGeoPcon as demonstrated by the attached macro. I would have expected the track in the macro to intersect the TGeoPcon, but it does not. Making either x or y for the initial
point, pos, as small as 1e-7, rather than zero, does make the track intersect.
I guess that this is a small enough error as to be negligible, but it did perplex me a bit when testing the tracking for a more complicated geometry.

There is nothing going wrong with the pcon in your example - it is normal to behave like this. If you shoot a ray from (0,0,500) in the direction (0,0,-1) in your case - you should have 3 crossings: first at z=250 with the top node, second at z=0 with the pcon and third at z=-250 again with the top node. Your output looks like:

Stepping 250 cm to next boundary.

Current node: /TOP_1: pos (0, 0, 250)
Stepping 250 cm to next boundary
Current node: /TOP_1: pos (0, 0, 3.328e-07)
Stepping 250 cm to next boundary

You worry about the second step, where the modeller reports is in the TOP node - it is OK since the width of the pcon in the crossed region is 0 and the default behavior of Step() method is to try to cross the boundary making an extra small step of 1E-6. Therefore, after Step() you will land again in TOP. Of course that if you shift a little the initial x/y, the width of the pcon will be big enough to produce a step inside it.
In order to test the crossed nodes rather than the node after making the step, you shoud investigate the node pointer returned by FindNextBoundary. If you print this name, the output of your macro becomes:

Stepping 250 cm to TOP_1 boundary.

Current node: /TOP_1: pos (0, 0, 250)
Stepping 250 cm to PVOL_1 boundary
Current node: /TOP_1: pos (0, 0, 3.328e-07)
Stepping 250 cm to TOP_1 boundary