The UGI checkTGTAndReloginFromKeytab() method checks certain conditions and if they are met it invokes the reloginFromKeytab(). The reloginFromKeytab() method then fails with an IOException "loginUserFromKeyTab must be done first" because there is no keytab associated with the UGI.
The checkTGTAndReloginFromKeytab() method checks if there is a keytab (isKeytab UGI instance variable) associated with the UGI, if there is one it triggers a call to reloginFromKeytab(). The problem is that the keytabFile UGI instance variable is NULL, and that triggers the mentioned IOException.
The root of the problem seems to be when creating a UGI via the UGI.loginUserFromSubject(Subject) method, this method uses the UserGroupInformation(Subject) constructor, and this constructor does the following to determine if there is a keytab or not.
If the Subject given had a keytab, then the UGI instance will have the isKeytab set to TRUE.
It sets the UGI instance as it would have a keytab because the Subject has a keytab. This has 2 problems:
First, it does not set the keytab file (and this, having the isKeytab set to TRUE and the keytabFile set to NULL) is what triggers the IOException in the method reloginFromKeytab().
Second (and even if the first problem is fixed, this still is a problem), it assumes that because the subject has a keytab it is up to UGI to do the relogin using the keytab. This is incorrect if the UGI was created using the UGI.loginUserFromSubject(Subject) method. In such case, the owner of the Subject is not the UGI, but the caller, so the caller is responsible for renewing the Kerberos tickets and the UGI should not try to do so.