Index: trunk/ppStack/src/ppStackLoop.c
===================================================================
--- trunk/ppStack/src/ppStackLoop.c	(revision 27004)
+++ trunk/ppStack/src/ppStackLoop.c	(revision 27075)
@@ -9,4 +9,46 @@
 #include "ppStack.h"
 #include "ppStackLoop.h"
+
+/// Print a summary of the inputs, and return the number of good inputs
+static int stackSummary(const ppStackOptions *options, // Stack options, with input mask
+                        const char *place              // Place in code
+    )
+{
+    int numGood = 0;                // Number of good inputs
+    psString summary = NULL;        // Summary of images
+    for (int i = 0; i < options->num; i++) {
+        char *reason;               // Reason for rejecting
+        switch (options->inputMask->data.PS_TYPE_VECTOR_MASK_DATA[i]) {
+          case PPSTACK_MASK_NONE:
+            reason = "Good";
+            numGood++;
+            break;
+          case PPSTACK_MASK_CAL:
+            reason = "Calibration failed";
+            break;
+          case PPSTACK_MASK_PSF:
+            reason = "PSF measurement failed";
+            break;
+          case PPSTACK_MASK_MATCH:
+            reason = "PSF matching failed";
+            break;
+          case PPSTACK_MASK_CHI2:
+            reason = "PSF matching chi^2 deviant";
+            break;
+          case PPSTACK_MASK_REJECT:
+            reason = "Rejection exceeded threshold";
+            break;
+          default:
+            psAbort("Unrecognised mask value: %x", options->inputMask->data.PS_TYPE_VECTOR_MASK_DATA[i]);
+        }
+        psStringAppend(&summary, "Image %d: %s\n", i, reason);
+    }
+    psLogMsg("ppStack", PS_LOG_INFO, "Summary of images for %s:\n%s", place, summary);
+    psFree(summary);
+
+    return numGood;
+}
+
+
 
 bool ppStackLoop(pmConfig *config)
@@ -53,4 +95,14 @@
     ppStackMemDump("convolve");
 
+    // Ensure sufficient inputs
+    {
+        int numGood = stackSummary(options, "initial combination");
+        psMetadata *recipe = psMetadataLookupMetadata(NULL, config->recipes, PPSTACK_RECIPE); // ppStack recipe
+        bool safe = psMetadataLookupBool(NULL, recipe, "SAFE"); // Be safe when combining
+        if (safe && numGood <= 1) {
+            psError(PPSTACK_ERR_REJECTED, true, "Insufficient inputs for combination with safety on");
+            return false;
+        }
+    }
 
     // Start threading
@@ -94,4 +146,12 @@
     ppStackMemDump("reject");
 
+    // Check inputs
+    {
+        int numGood = stackSummary(options, "final combination");
+        if (numGood <= 0) {
+            psError(PPSTACK_ERR_REJECTED, true, "Insufficient inputs for combination");
+            return false;
+        }
+    }
 
     // Final combination
