{"record":{"id":"d9681506bb94bcf4","repo":"apache/hadoop","slug":"user-is-null-while-setting-up-jobhistory-eventwrit","errorCode":null,"errorMessage":"User is null while setting up jobhistory eventwriter","messagePattern":"User is null while setting up jobhistory eventwriter","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/jobhistory/JobHistoryEventHandler.java","lineNumber":532,"sourceCode":"   * @throws IOException\n   */\n  protected void setupEventWriter(JobId jobId, AMStartedEvent amStartedEvent)\n      throws IOException {\n    if (stagingDirPath == null) {\n      LOG.error(\"Log Directory is null, returning\");\n      throw new IOException(\"Missing Log Directory for History\");\n    }\n\n    MetaInfo oldFi = fileMap.get(jobId);\n    Configuration conf = getConfig();\n\n    // TODO Ideally this should be written out to the job dir\n    // (.staging/jobid/files - RecoveryService will need to be patched)\n    Path historyFile = JobHistoryUtils.getStagingJobHistoryFile(\n        stagingDirPath, jobId, startCount);\n    String user = UserGroupInformation.getCurrentUser().getShortUserName();\n    if (user == null) {\n      throw new IOException(\n          \"User is null while setting up jobhistory eventwriter\");\n    }\n\n    String jobName = context.getJob(jobId).getName();\n    EventWriter writer = (oldFi == null) ? null : oldFi.writer;\n \n    Path logDirConfPath =\n        JobHistoryUtils.getStagingConfFile(stagingDirPath, jobId, startCount);\n    if (writer == null) {\n      try {\n        writer = createEventWriter(historyFile);\n        LOG.info(\"Event Writer setup for JobId: \" + jobId + \", File: \"\n            + historyFile);\n      } catch (IOException ioe) {\n        LOG.info(\"Could not create log file: [\" + historyFile + \"] + for job \"\n            + \"[\" + jobName + \"]\");\n        throw ioe;\n      }","sourceCodeStart":514,"sourceCodeEnd":550,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/jobhistory/JobHistoryEventHandler.java#L514-L550","documentation":"setupEventWriter resolves the job's owner with UserGroupInformation.getCurrentUser().getShortUserName() and refuses to create the history event writer when that returns null. A null short user name means the UGI subject carries no usable principal (empty or malformed user string), so the AM cannot attribute ownership to the history files and aborts.","triggerScenarios":"AM executes inside a Subject whose principal yields no short name (broken doAs); simple-auth environment producing a blank user (bad HADOOP_USER_NAME); Kerberos login with a principal the JVM cannot parse into a short name.","commonSituations":"Custom UGI.doAs wrappers around job submission or AM code; SPNEGO/Kerberos misconfiguration (missing realm mapping); containers launched with corrupted user environment after NM changes; edge cases after Hadoop security upgrades.","solutions":["Check which OS/JVM user the AM container runs as and that UserGroupInformation.getCurrentUser().getShortUserName() returns a name (test with 'hadoop kerbname' or a small UGI dump)","Set a valid HADOOP_USER_NAME for simple auth, or fix the Kerberos principal/user mapping (hadoop.security.auth_to_local) so login produces a real short name","If the error appears only under a custom doAs, unwrap the Subject before history setup or use UserGroupInformation.createRemoteUser with a concrete name"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// sanity-check identity before launching jobs/AMs under custom subjects\nUserGroupInformation ugi = UserGroupInformation.getCurrentUser();\nString user = ugi.getShortUserName();\nif (user == null || user.isEmpty()) {\n  throw new IllegalStateException(\"No resolvable short user name for \" + ugi);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always set a concrete HADOOP_USER_NAME or a valid Kerberos principal for job/AM processes","Test doAs wrappers by asserting UserGroupInformation.getCurrentUser().getShortUserName() is non-null before submission","Keep hadoop.security.auth_to_local mappings valid so principals convert to real short names"],"tags":["mapreduce","job-history","ugi","kerberos","user-identity"],"backgroundTag":"null-current-user","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}