Fix insertion cross space compaction recover null pointer exception (#12439)

* fix insertion cross space compaction null pointer

* add ut
diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/compaction/execute/task/InsertionCrossSpaceCompactionTask.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/compaction/execute/task/InsertionCrossSpaceCompactionTask.java
index 6f262a7..d813bd0 100644
--- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/compaction/execute/task/InsertionCrossSpaceCompactionTask.java
+++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/compaction/execute/task/InsertionCrossSpaceCompactionTask.java
@@ -85,6 +85,8 @@
     super(databaseName, dataRegionId, 0L, tsFileManager, 0L, CompactionTaskPriorityType.NORMAL);
     this.logFile = logFile;
     this.needRecoverTaskInfoFromLogFile = true;
+    this.selectedSeqFiles = Collections.emptyList();
+    this.selectedUnseqFiles = new ArrayList<>(1);
   }
 
   private TsFileResource unseqFileToInsert;
@@ -242,6 +244,7 @@
     File sourceTsFile = sourceFileIdentifiers.get(0).getFileFromDataDirsIfAnyAdjuvantFileExists();
     if (sourceTsFile != null) {
       unseqFileToInsert = new TsFileResource(sourceTsFile);
+      selectedUnseqFiles.add(unseqFileToInsert);
     }
     File targetTsFile = targetFileIdentifiers.get(0).getFileFromDataDirsIfAnyAdjuvantFileExists();
     if (targetTsFile != null) {
@@ -288,7 +291,9 @@
     return targetFile == null
         || !targetFile.tsFileExists()
         || !targetFile.resourceFileExists()
-        || (unseqFileToInsert.modFileExists() && !targetFile.modFileExists());
+        || (unseqFileToInsert != null
+            && unseqFileToInsert.modFileExists()
+            && !targetFile.modFileExists());
   }
 
   private void rollback() throws IOException {
@@ -298,6 +303,9 @@
           Collections.singletonList(targetFile), Collections.singletonList(unseqFileToInsert));
     }
     deleteCompactionModsFile(Collections.singletonList(unseqFileToInsert));
+    if (targetFile == null) {
+      return;
+    }
     if (targetFile.tsFileExists()) {
       FileMetrics.getInstance().deleteTsFile(true, Collections.singletonList(targetFile));
     }
@@ -309,6 +317,9 @@
   }
 
   private void finishTask() throws IOException {
+    if (unseqFileToInsert == null) {
+      return;
+    }
     if (recoverMemoryStatus && unseqFileToInsert.tsFileExists()) {
       FileMetrics.getInstance().deleteTsFile(false, Collections.singletonList(unseqFileToInsert));
     }
diff --git a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/storageengine/dataregion/compaction/cross/InsertionCrossSpaceCompactionRecoverTest.java b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/storageengine/dataregion/compaction/cross/InsertionCrossSpaceCompactionRecoverTest.java
index e99d2c7..69b4bc9 100644
--- a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/storageengine/dataregion/compaction/cross/InsertionCrossSpaceCompactionRecoverTest.java
+++ b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/storageengine/dataregion/compaction/cross/InsertionCrossSpaceCompactionRecoverTest.java
@@ -345,6 +345,88 @@
     Assert.assertTrue(targetFile.modFileExists());
   }
 
+  @Test
+  public void testRecoverWithTargetFileNotExist()
+      throws IllegalPathException, IOException, MergeException {
+    IDeviceID d1 = new PlainDeviceID("root.testsg.d1");
+    IDeviceID d2 = new PlainDeviceID("root.testsg.d2");
+
+    TsFileResource seqResource1 = createTsFileResource("1-1-0-0.tsfile", true);
+    seqResource1.updateStartTime(d1, 10);
+    seqResource1.updateEndTime(d1, 20);
+    seqResource1.updateStartTime(d2, 20);
+    seqResource1.updateEndTime(d2, 30);
+    createTsFileByResource(seqResource1);
+    seqResource1.serialize();
+
+    TsFileResource seqResource2 = createTsFileResource("3-3-0-0.tsfile", true);
+    seqResource2.updateStartTime(d1, 30);
+    seqResource2.updateEndTime(d1, 40);
+    seqResource2.updateStartTime(d2, 40);
+    seqResource2.updateEndTime(d2, 50);
+    createTsFileByResource(seqResource2);
+    seqResource2.serialize();
+
+    seqResources.add(seqResource1);
+    seqResources.add(seqResource2);
+
+    TsFileResource unseqResource1 = createTsFileResource("9-9-0-0.tsfile", false);
+    unseqResource1.updateStartTime(d1, 22);
+    unseqResource1.updateEndTime(d1, 25);
+    unseqResource1.updateStartTime(d2, 31);
+    unseqResource1.updateEndTime(d2, 37);
+    createTsFileByResource(unseqResource1);
+    unseqResource1.serialize();
+
+    Map<String, Pair<Long, Long>> deleteMap = new HashMap<>();
+    deleteMap.put(((PlainDeviceID) d1).toStringID() + ".s1", new Pair<>(0L, 300L));
+    CompactionFileGeneratorUtils.generateMods(deleteMap, unseqResource1, false);
+
+    unseqResources.add(unseqResource1);
+
+    tsFileManager.addAll(seqResources, true);
+    tsFileManager.addAll(unseqResources, false);
+
+    RewriteCrossSpaceCompactionSelector selector =
+        new RewriteCrossSpaceCompactionSelector("root.testsg", "0", 0, tsFileManager);
+    InsertionCrossCompactionTaskResource taskResource =
+        selector.selectOneInsertionTask(
+            new CrossSpaceCompactionCandidate(seqResources, unseqResources));
+    Assert.assertEquals(unseqResource1, taskResource.toInsertUnSeqFile);
+    Assert.assertEquals(seqResource1, taskResource.prevSeqFile);
+    Assert.assertEquals(seqResource2, taskResource.nextSeqFile);
+    Assert.assertEquals(unseqResource1, taskResource.firstUnSeqFileInParitition);
+
+    InsertionCrossSpaceCompactionTask task =
+        new InsertionCrossSpaceCompactionTask(new Phaser(), 0, tsFileManager, taskResource, 0);
+    TsFileResource targetFile = new TsFileResource(task.generateTargetFile());
+    File logFile =
+        new File(
+            targetFile.getTsFilePath() + CompactionLogger.INSERTION_COMPACTION_LOG_NAME_SUFFIX);
+
+    CompactionFileGeneratorUtils.generateMods(deleteMap, unseqResource1, true);
+
+    try (SimpleCompactionLogger logger = new SimpleCompactionLogger(logFile)) {
+      logger.logSourceFile(taskResource.toInsertUnSeqFile);
+      logger.logTargetFile(targetFile);
+      logger.force();
+    }
+
+    // recover compaction, all target file and compaction.mods file should be deleted and source
+    // file should be existed
+    new InsertionCrossSpaceCompactionTask("root.testsg", "0", tsFileManager, logFile).recover();
+
+    Assert.assertTrue(unseqResource1.getTsFile().exists());
+    Assert.assertTrue(
+        new File(unseqResource1.getTsFilePath() + TsFileResource.RESOURCE_SUFFIX).exists());
+    Assert.assertTrue(unseqResource1.getModFile().exists());
+    Assert.assertFalse(unseqResource1.getCompactionModFile().exists());
+
+    Assert.assertFalse(targetFile.tsFileExists());
+    Assert.assertFalse(targetFile.resourceFileExists());
+    Assert.assertFalse(targetFile.modFileExists());
+  }
+
   private TsFileResource createTsFileResource(String name, boolean seq) {
     String filePath = (seq ? SEQ_DIRS : UNSEQ_DIRS) + File.separator + name;
     TsFileResource resource = new TsFileResource();