docs: SnapshotInfo generatePlans() throws Exception {
          Map<String, Snapshot> snapshots = new HashMap<String, SnapshotUtil.Snapshot>();
  
          // Only scan if startup might require a snapshot restore.
          if (m_action.doesRecover()) {
              snapshots = getSnapshots();
          }
  
          final Long maxLastSeenTxn = m_replayAgent.getMaxLastSeenTxn();
          Set<SnapshotInfo> snapshotInfos = new HashSet<SnapshotInfo>();
          for (Snapshot e : snapshots.values()) {
              SnapshotInfo info = checkSnapshotIsComplete(e.getTxnId(), e);
              // if the cluster instance IDs in the snapshot and command log don't match, just move along
              if (m_replayAgent.getInstanceId() != null && info != null &&
                  !m_replayAgent.getInstanceId().equals(info.instanceId)) {
                  // Exceptions are not well tolerated here, so don't throw over something
                  // as trivial as error message formatting.
                  String agentIdString;
                  String infoIdString;
                  try {
                      agentIdString = m_replayAgent.getInstanceId().serializeToJSONObject().toString();
                  } catch (JSONException e1) {
                      agentIdString = "<failed to serialize id>";
                  }
                  try {
                      infoIdString = info.instanceId.serializeToJSONObject().toString();
                  } catch (JSONException e1) {
                      infoIdString = "<failed to serialize id>";
                  }
                  m_snapshotErrLogStr.append("\nRejected snapshot ")
                  .append(info.nonce)
                  .append(" due to mismatching instance IDs.")
                  .append(" Command log ID: ")
                  .append(agentIdString)
                  .append(" Snapshot ID: ")
                  .append(infoIdString);
                  continue;
              }
              if (info != null) {
                  final Map<Integer, Long> cmdlogmap = m_replayAgent.getMaxLastSeenTxnByPartition();
                  final Map<Integer, Long> snapmap = info.partitionToTxnId;
                  // If cmdlogmap is null, there were no command log segments, so all snapshots are potentially valid,
                  // don't do any TXN ID consistency checking between command log and snapshot
                  if (cmdlogmap != null) {
                      for (Integer cmdpart : cmdlogmap.keySet()) {
                          Long snaptxnId = snapmap.get(cmdpart);
                          if (snaptxnId == null) {
                              m_snapshotErrLogStr.append("\nRejected snapshot ")
                                              .append(info.nonce)
                                              .append(" due to missing partition: ")
                                              .append(cmdpart);
                              info = null;
                              break;
                          }
                          else if (snaptxnId < cmdlogmap.get(cmdpart)) {
                              m_snapshotErrLogStr.append("\nRejected snapshot ")
                                              .append(info.nonce)
                                              .append(" because it does not overlap the command log")
                                              .append(" for partition: ")
                                              .append(cmdpart)
                                              .append(" command log txn ID: ")
                                              .append(cmdlogmap.get(cmdpart))
                                              .append(" snapshot txn ID: ")
                                              .append(snaptxnId);
                              info = null;
                              break;
                          }
                      }
                  }
              }
  
  
              if (info != null) {
                  snapshotInfos.add(info);
              }
          }
          if (LOG.isDebugEnabled()) {
              LOG.debug("Gathered " + snapshotInfos.size() + " snapshot information");
          }
          sendLocalRestoreInformation(maxLastSeenTxn, snapshotInfos);
  
          // Negotiate with other hosts about which snapshot to restore
          SnapshotInfo infoWithMinHostId = getRestorePlan();
          if (infoWithMinHostId != null && infoWithMinHostId.nonce.equals(m_terminusNonce)) {
              m_replayAgent.returnAllSegments();
              initialize(StartAction.CREATE);
              m_planned = true;
              return infoWithMinHostId;
          }
  
          /*
           * Generate the replay plan here so that we don't have to wait until the
           * snapshot restore finishes.
           */
          if (m_action.doesRecover()) {
              if (infoWithMinHostId != null) {
                  // The expected partition count could be determined by the new partition count recorded
                  // in the truncation snapshot. Truncation snapshot taken at the end of the join process
                  // actually records the new partition count in the digest.
                  m_replayAgent.generateReplayPlan(infoWithMinHostId.instanceId.getTimestamp(),
                          infoWithMinHostId.txnId, infoWithMinHostId.newPartitionCount, m_isLeader,
                          infoWithMinHostId.elasticOperationMetadata);
              }
          }
  
          m_planned = true;
          return infoWithMinHostId;
      }