apache/hadoop · critical · JournalOutOfSyncException

No log file to finalize at transaction ID {} ; journal id: {

Error message

No log file to finalize at transaction ID {} ; journal id: {}

What it means

Journal.finalizeLogSegment throws JournalOutOfSyncException (an IOException) when the writer requests finalization of the segment starting at startTxId but FileJournalManager.getLogFile(startTxId) finds no edit log file at all on disk for that txid. It means the journal and the NameNode disagree about which segments exist — the journal is missing a segment the writer believes it wrote. HDFS treats this as a hard out-of-sync signal; the segment cannot be finalized because there is nothing to finalize.

Source

Thrown at hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/qjournal/server/Journal.java:656

      if (curSegment != null) {
        curSegment.close();
        curSegment = null;
        curSegmentTxId = HdfsServerConstants.INVALID_TXID;
        curSegmentLayoutVersion = 0;
      }
      
      checkSync(nextTxId == endTxId + 1,
          "Trying to finalize in-progress log segment %s to end at " +
          "txid %s but only written up to txid %s ; journal id: %s",
          startTxId, endTxId, nextTxId - 1, journalId);
      // No need to validate the edit log if the client is finalizing
      // the log segment that it was just writing to.
      needsValidation = false;
    }
    
    FileJournalManager.EditLogFile elf = fjm.getLogFile(startTxId);
    if (elf == null) {
      throw new JournalOutOfSyncException("No log file to finalize at " +
          "transaction ID " + startTxId + " ; journal id: " + journalId);
    }

    if (elf.isInProgress()) {
      if (needsValidation) {
        LOG.info("Validating log segment " + elf.getFile() + " about to be " +
            "finalized ; journal id: " + journalId);
        elf.scanLog(Long.MAX_VALUE, false);
  
        checkSync(elf.getLastTxId() == endTxId,
            "Trying to finalize in-progress log segment %s to end at " +
            "txid %s but log %s on disk only contains up to txid %s " +
            "; journal id: %s",
            startTxId, endTxId, elf.getFile(), elf.getLastTxId(), journalId);
      }
      fjm.finalizeLogSegment(startTxId, endTxId);
    } else {
      Preconditions.checkArgument(endTxId == elf.getLastTxId(),

View on GitHub (pinned to 2add963021)

Solutions

  1. Compare the journal's on-disk segments with the NameNode's expectation via getEditLogManifest (or the JournalNode HTTP /journalextension or listing the current/prev dirs) to see exactly which segments the journal holds.
  2. If the journal lost data, resync it from healthy journals of the same journal id: stop the JournalNode, wipe its dfs.journalnode.edits.dir for that jid, restart, then run 'hdfs journalnode -bootstrap' style sync or let the NN re-tail edits so the empty journal is refilled from peers.
  3. If the segment was already finalized by recovery, the finalize retry is benign — restart/fail-over the NameNode so it refreshes its view of journal state instead of retrying the stale finalize.
  4. Check JournalNode logs and disk health (df, dmesg) for the underlying loss; enable dfs.journalnode.enable.sync (edit-tailer between JNs) to keep lagging journals consistent.

Example fix

// before: NN retries finalize against a journal that lost the segment
// JournalOutOfSyncException: No log file to finalize at transaction ID 1234 ; journal id: myjournal

// after (operational fix): resync the empty journal from peers
// 1) stop JournalNode, remove /journal/myjournal/current for that jid
// 2) restart JournalNode with edit-sync enabled so it tails missing segments
<property>
  <name>dfs.journalnode.enable.sync</name>
  <value>true</value>
</property>
Defensive patterns

Strategy: try-catch

Validate before calling

// Verify the segment exists on this journal before finalizing
RemoteEditLogManifest manifest = journal.getEditLogManifest(startTxId, true);
boolean present = manifest.getLogs().stream()
    .anyMatch(l -> l.getStartTxId() == startTxId);
if (!present) { /* journal is out of sync: resync it before finalize */ }

Try / catch

try {
  journal.finalizeLogSegment(reqInfo, startTxId, endTxId);
} catch (JournalOutOfSyncException e) {
  // this journal lost/never had the segment: fail over or resync journal from peers;
  // do not blind-retry against the same out-of-sync journal
  failoverOrResyncJournal(journalId);
}

Prevention

When it happens

Trigger: QJournalProtocol.finalizeLogSegment(startTxId, endTxId) is called while (a) the journal restarted and lost/replaced its edit dirs, (b) a previous recovery already finalized or purged the segment, or (c) the journal directory was truncated/corrupted so fjm.getLogFile(startTxId) returns null.

Common situations: JournalNode disk loss or replacement under the same journal id; journal dir partially wiped or restored from an old backup; segment already finalized during epoch recovery and a lagging writer retries the old finalize; mixing journal dirs between clusters; JournalNode pointing at an empty mount after an NFS/storage hiccup.

Related errors


AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22). Data as JSON: /api/errors/ef8cc720a7968c3a. Report an issue: GitHub.