This problem is due to the order in which javac perform attribution of type-variable bounds wrt class attribution.
1) Attribution of class Outer<T extends Outer.Inner>
1a) Attribution of Outer triggers attribution of Outer's type variable
2) Attribution of Outer.T
2a) Attribution of Outer.T triggers attribution of its declared bound
3) Attribution of class Outer.Inner<S extends T>
3a) Attribution of Outer.Inner triggers attribution of Outer.Inner's type variable
4) Attribution of Outer.Inner<S>
4a) Attribution of Outer.Inner.S triggers attribution of its declared bound
5) Attribution of Outer.T - this does nothing but returning the type of T; as you can see, at this stage T's bound has not been set yet on the object representing the type of T.
At a later point, for each attributed type variable, javac performs a check to ensure that the bound of a given type variable does not introduce cyclic inheritance. But we have seen that no bound is set for Outer.T; for this is the reason javac crashes with a NPE when trying to detect a cycle in the inheritance tree induced by the declared bound of Outer.Inner.S.
The solution is to postpone the acyclicity checking after all the type-variable bounds have been attributed. Proper bound types will be set on their corresponding TypeVar objects as a side-effect of the whole attribution process.