Index: /trunk/ppSub/src/ppSub.c
===================================================================
--- /trunk/ppSub/src/ppSub.c	(revision 26981)
+++ /trunk/ppSub/src/ppSub.c	(revision 26982)
@@ -24,24 +24,10 @@
 int main(int argc, char *argv[])
 {
-
-# if 0
     psLibInit(NULL);
-    pmVisualSetVisual(true);
-    for (int order = 2; order < 11; order ++) {
-	pmSubtractionDeconvolutionTest (order);
-    }
-    psLibFinalize();
-    exit (1);
-# endif
-
-    psExit exitValue = PS_EXIT_SUCCESS; // Exit value
     psTimerStart("ppSub");
-    psLibInit(NULL);
 
     ppSubData *data = NULL;             // Processing data
     pmConfig *config = pmConfigRead(&argc, argv, PPSUB_RECIPE); // Configuration
     if (!config) {
-        psErrorStackPrint(stderr, "Error reading configuration.");
-        exitValue = PS_EXIT_CONFIG_ERROR;
         goto die;
     }
@@ -50,6 +36,5 @@
 
     if (!pmModelClassInit()) {
-        psErrorStackPrint(stderr, "Error initialising model classes.\n");
-        exitValue = PS_EXIT_PROG_ERROR;
+        psError(PPSUB_ERR_PROG, false, "Unable to initialise model classes.");
         psFree(config);
         goto die;
@@ -57,6 +42,5 @@
 
     if (!psphotInit()) {
-        psErrorStackPrint(stderr, "Error initialising psphot.\n");
-        exitValue = PS_EXIT_PROG_ERROR;
+        psError(PPSUB_ERR_PROG, false, "Error initialising psphot.");
         psFree(config);
         goto die;
@@ -66,18 +50,13 @@
 
     if (!ppSubArguments(argc, argv, data)) {
-        psErrorStackPrint(stderr, "Error reading arguments.\n");
-        exitValue = PS_EXIT_CONFIG_ERROR;
+        psError(PPSUB_ERR_ARGUMENTS, false, "Error reading arguments.");
         goto die;
     }
 
     if (!ppSubCamera(data)) {
-        psErrorStackPrint(stderr, "Error setting up camera.\n");
-        exitValue = PS_EXIT_CONFIG_ERROR;
         goto die;
     }
 
     if (!ppSubLoop(data)) {
-        psErrorStackPrint(stderr, "Error performing subtraction.\n");
-        exitValue = PS_EXIT_SYS_ERROR;
         goto die;
     }
@@ -87,12 +66,13 @@
     psTimerStop();
 
-    psString dump_file = psMetadataLookupStr(NULL, data->config->arguments, "-dumpconfig");
-    if (dump_file) {
-        if (!pmConfigDump(data->config, dump_file)) {
-            psErrorStackPrint(stderr, "Unable to dump configuration.\n");
-            exitValue = PS_EXIT_SYS_ERROR;
+    if (data) {
+        psString dump_file = psMetadataLookupStr(NULL, data->config->arguments, "-dumpconfig");
+        if (dump_file) {
+            if (!pmConfigDump(data->config, dump_file)) {
+                psError(PPSUB_ERR_IO, false, "Unable to dump configuration.");
+            }
         }
+        psFree(data);
     }
-    psFree(data);
 
     pmVisualClose(); //close plot windows, if -visual is set
@@ -101,4 +81,44 @@
     psLibFinalize();
 
+    psExit exitValue = PS_EXIT_SUCCESS;        // Exit value for program
+    psErrorCode errorCode = psErrorCodeLast(); // Error code
+    if (errorCode != PS_ERR_NONE) {
+        psErrorStackPrint(stderr, "Unable to perform subtraction.");
+        switch (errorCode) {
+          case PPSUB_ERR_UNKNOWN:
+          case PS_ERR_UNKNOWN:
+            exitValue = PS_EXIT_UNKNOWN_ERROR;
+            break;
+          case PS_ERR_IO:
+          case PS_ERR_DB_CLIENT:
+          case PS_ERR_DB_SERVER:
+          case PS_ERR_BAD_FITS:
+          case PS_ERR_OS_CALL_FAILED:
+          case PPSUB_ERR_IO:
+            exitValue = PS_EXIT_SYS_ERROR;
+            break;
+          case PS_ERR_BAD_PARAMETER_VALUE:
+          case PS_ERR_BAD_PARAMETER_TYPE:
+          case PS_ERR_BAD_PARAMETER_NULL:
+          case PS_ERR_BAD_PARAMETER_SIZE:
+          case PPSUB_ERR_ARGUMENTS:
+          case PPSUB_ERR_CONFIG:
+            exitValue = PS_EXIT_CONFIG_ERROR;
+            break;
+          case PPSUB_ERR_DATA:
+          case PPSUB_ERR_NO_OVERLAP:
+            exitValue = PS_EXIT_DATA_ERROR;
+            break;
+          case PS_ERR_UNEXPECTED_NULL:
+          case PS_ERR_PROGRAMMING:
+          case PPSUB_ERR_NOT_IMPLEMENTED:
+          case PPSUB_ERR_PROG:
+          default:
+            // It's a programming error if we're not dealing with the error correctly
+            exitValue = PS_EXIT_PROG_ERROR;
+            break;
+        }
+    }
+
     exit(exitValue);
 }
Index: /trunk/ppSub/src/ppSubBackground.c
===================================================================
--- /trunk/ppSub/src/ppSubBackground.c	(revision 26981)
+++ /trunk/ppSub/src/ppSubBackground.c	(revision 26982)
@@ -43,5 +43,5 @@
         // Create the background model
         if (!psphotModelBackgroundReadoutFileIndex(config, view, "PPSUB.OUTPUT", 0)) {
-            psError(PS_ERR_UNKNOWN, false, "Unable to model background");
+            psError(psErrorCodeLast(), false, "Unable to model background");
             psFree(view);
             return false;
@@ -50,5 +50,5 @@
         modelRO = pmFPAfileThisReadout(config->files, view, "PSPHOT.BACKMDL");
         if (!modelRO) {
-            psError(PS_ERR_UNEXPECTED_NULL, true, "Unable to find background model");
+            psError(psErrorCodeLast(), false, "Unable to find background model");
             psFree(view);
             return false;
Index: /trunk/ppSub/src/ppSubCamera.c
===================================================================
--- /trunk/ppSub/src/ppSubCamera.c	(revision 26981)
+++ /trunk/ppSub/src/ppSubCamera.c	(revision 26982)
@@ -45,5 +45,5 @@
 
     if (!status) {
-        psError(PS_ERR_UNKNOWN, false, "Failed to load file definition for %s", filerule);
+        psError(psErrorCodeLast(), false, "Failed to load file definition for %s", filerule);
         return false;
     }
@@ -52,5 +52,5 @@
         file = pmFPAfileDefineFromRun(&status, bind, config, filerule); // File to return
         if (!status) {
-            psError(PS_ERR_UNKNOWN, false, "Failed to load file definition for %s", filerule);
+            psError(psErrorCodeLast(), false, "Failed to load file definition for %s", filerule);
             return NULL;
         }
@@ -64,5 +64,5 @@
 
     if (file->type != fileType) {
-        psError(PS_ERR_UNKNOWN, true, "%s is not of type %s", filerule, pmFPAfileStringFromType(fileType));
+        psError(PPSUB_ERR_CONFIG, true, "%s is not of type %s", filerule, pmFPAfileStringFromType(fileType));
         return NULL;
     }
@@ -84,9 +84,9 @@
         pmFPAfileDefineOutput(config, template->fpa, filerule);
     if (!file) {
-        psError(PS_ERR_IO, false, _("Unable to generate output file from %s"), filerule);
+        psError(psErrorCodeLast(), false, _("Unable to generate output file from %s"), filerule);
         return NULL;
     }
     if (file->type != fileType) {
-        psError(PS_ERR_IO, true, "%s is not of type %s", filerule, pmFPAfileStringFromType(fileType));
+        psError(PPSUB_ERR_CONFIG, true, "%s is not of type %s", filerule, pmFPAfileStringFromType(fileType));
         return NULL;
     }
@@ -109,5 +109,5 @@
     pmFPAfile *file = pmFPAfileDefineFromRun(&status, bind, config, filerule); // File to return
     if (!status) {
-        psError(PS_ERR_UNKNOWN, false, "Failed to load file definition for %s", filerule);
+        psError(psErrorCodeLast(), false, "Failed to load file definition for %s", filerule);
         return NULL;
     }
@@ -121,5 +121,5 @@
         file = pmFPAfileDefineOutput(config, bind ? bind->fpa : NULL, filerule);
         if (!status) {
-            psError(PS_ERR_UNKNOWN, false, "Failed to load file definition for %s", filerule);
+            psError(psErrorCodeLast(), false, "Failed to load file definition for %s", filerule);
             return false;
         }
@@ -135,5 +135,5 @@
 
     if (file->type != fileType) {
-        psError(PS_ERR_UNKNOWN, true, "%s is not of type %s", filerule, pmFPAfileStringFromType(fileType));
+        psError(PPSUB_ERR_CONFIG, true, "%s is not of type %s", filerule, pmFPAfileStringFromType(fileType));
         return NULL;
     }
@@ -154,5 +154,5 @@
     pmFPAfile *input = defineInputFile(&success, config, NULL, "PPSUB.INPUT", "INPUT", PM_FPA_FILE_IMAGE);
     if (!success) {
-        psError(PS_ERR_IO, false, "Failed to build FPA from PPSUB.INPUT");
+        psError(psErrorCodeLast(), false, "Failed to build FPA from PPSUB.INPUT");
         return false;
     }
@@ -160,5 +160,5 @@
     defineInputFile(&success, config, input, "PPSUB.INPUT.MASK", "INPUT.MASK", PM_FPA_FILE_MASK);
     if (!success) {
-        psError(PS_ERR_IO, false, "Failed to build FPA from PPSUB.INPUT.MASK");
+        psError(psErrorCodeLast(), false, "Failed to build FPA from PPSUB.INPUT.MASK");
         return false;
     }
@@ -166,5 +166,5 @@
     pmFPAfile *inVar = defineInputFile(&success, config, input, "PPSUB.INPUT.VARIANCE", "INPUT.VARIANCE", PM_FPA_FILE_VARIANCE);
     if (!success) {
-        psError(PS_ERR_IO, false, "Failed to build FPA from PPSUB.INPUT.VARIANCE");
+        psError(psErrorCodeLast(), false, "Failed to build FPA from PPSUB.INPUT.VARIANCE");
         return false;
     }
@@ -172,5 +172,5 @@
     defineInputFile(&success, config, NULL, "PPSUB.INPUT.SOURCES", "INPUT.SOURCES", PM_FPA_FILE_CMF);
     if (!success) {
-        psError(PS_ERR_IO, false, "Failed to build FPA from PPSUB.INPUT.SOURCES");
+        psError(psErrorCodeLast(), false, "Failed to build FPA from PPSUB.INPUT.SOURCES");
         return false;
     }
@@ -179,5 +179,5 @@
     pmFPAfile *ref = defineInputFile(&success, config, NULL, "PPSUB.REF", "REF", PM_FPA_FILE_IMAGE);
     if (!success) {
-        psError(PS_ERR_IO, false, "Failed to build FPA from PPSUB.REF");
+        psError(psErrorCodeLast(), false, "Failed to build FPA from PPSUB.REF");
         return false;
     }
@@ -185,5 +185,5 @@
     defineInputFile(&success, config, ref, "PPSUB.REF.MASK", "REF.MASK", PM_FPA_FILE_MASK);
     if (!success) {
-        psError(PS_ERR_IO, false, "Failed to build FPA from PPSUB.REF.MASK");
+        psError(psErrorCodeLast(), false, "Failed to build FPA from PPSUB.REF.MASK");
         return false;
     }
@@ -191,5 +191,5 @@
     pmFPAfile *refVar = defineInputFile(&success, config, ref, "PPSUB.REF.VARIANCE", "REF.VARIANCE", PM_FPA_FILE_VARIANCE);
     if (!success) {
-        psError(PS_ERR_IO, false, "Failed to build FPA from PPSUB.REF.VARIANCE");
+        psError(psErrorCodeLast(), false, "Failed to build FPA from PPSUB.REF.VARIANCE");
         return false;
     }
@@ -197,5 +197,5 @@
     defineInputFile(&success, config, NULL, "PPSUB.REF.SOURCES", "REF.SOURCES", PM_FPA_FILE_CMF);
     if (!success) {
-        psError(PS_ERR_IO, false, "Failed to build FPA from PPSUB.REF.SOURCES");
+        psError(psErrorCodeLast(), false, "Failed to build FPA from PPSUB.REF.SOURCES");
         return false;
     }
@@ -204,5 +204,5 @@
     psMetadata *recipe = psMetadataLookupMetadata(NULL, config->recipes, PPSUB_RECIPE); // Recipe for ppSim
     if (!recipe) {
-        psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to find recipe %s", PPSUB_RECIPE);
+        psError(PPSUB_ERR_CONFIG, false, "Unable to find recipe %s", PPSUB_RECIPE);
         return false;
     }
@@ -227,5 +227,5 @@
                                              PM_FPA_FILE_MASK);
     if (!inConvImage || !inConvMask) {
-        psError(PS_ERR_UNKNOWN, false, "Unable to define output files");
+        psError(psErrorCodeLast(), false, "Unable to define output files");
         return false;
     }
@@ -238,5 +238,5 @@
                                                 PM_FPA_FILE_VARIANCE);
         if (!inConvVar) {
-            psError(PS_ERR_UNKNOWN, false, "Unable to define output files");
+            psError(psErrorCodeLast(), false, "Unable to define output files");
             return false;
         }
@@ -251,5 +251,5 @@
                                               PM_FPA_FILE_MASK);
     if (!refConvImage || !refConvMask) {
-        psError(PS_ERR_UNKNOWN, false, "Unable to define output files");
+        psError(psErrorCodeLast(), false, "Unable to define output files");
         return false;
     }
@@ -262,5 +262,5 @@
                                                  PM_FPA_FILE_VARIANCE);
         if (!refConvVar) {
-            psError(PS_ERR_UNKNOWN, false, "Unable to define output files");
+            psError(psErrorCodeLast(), false, "Unable to define output files");
             return false;
         }
@@ -274,5 +274,5 @@
     pmFPAfile *outMask = defineOutputFile(config, output, false, "PPSUB.OUTPUT.MASK", PM_FPA_FILE_MASK);
     if (!output || !outMask) {
-        psError(PS_ERR_UNKNOWN, false, "Unable to define output files");
+        psError(psErrorCodeLast(), false, "Unable to define output files");
         return false;
     }
@@ -283,5 +283,5 @@
                                              PM_FPA_FILE_VARIANCE);
         if (!outVar) {
-            psError(PS_ERR_UNKNOWN, false, "Unable to define output files");
+            psError(psErrorCodeLast(), false, "Unable to define output files");
             return false;
         }
@@ -296,5 +296,5 @@
                                               PM_FPA_FILE_MASK);
         if (!inverse || !invMask) {
-            psError(PS_ERR_UNKNOWN, false, "Unable to define output files");
+            psError(psErrorCodeLast(), false, "Unable to define output files");
             return false;
         }
@@ -305,5 +305,5 @@
                                                  PM_FPA_FILE_VARIANCE);
             if (!invVar) {
-                psError(PS_ERR_UNKNOWN, false, "Unable to define output files");
+                psError(psErrorCodeLast(), false, "Unable to define output files");
                 return false;
             }
@@ -316,9 +316,9 @@
     pmFPAfile *jpeg1 = pmFPAfileDefineOutput(config, NULL, "PPSUB.OUTPUT.JPEG1");
     if (!jpeg1) {
-        psError(PS_ERR_IO, false, _("Unable to generate output file from PPSUB.OUTPUT.JPEG1"));
+        psError(psErrorCodeLast(), false, _("Unable to generate output file from PPSUB.OUTPUT.JPEG1"));
         return false;
     }
     if (jpeg1->type != PM_FPA_FILE_JPEG) {
-        psError(PS_ERR_IO, true, "PPSUB.OUTPUT.JPEG1 is not of type JPEG");
+        psError(psErrorCodeLast(), true, "PPSUB.OUTPUT.JPEG1 is not of type JPEG");
         return false;
     }
@@ -326,9 +326,9 @@
     pmFPAfile *jpeg2 = pmFPAfileDefineOutput(config, NULL, "PPSUB.OUTPUT.JPEG2");
     if (!jpeg2) {
-        psError(PS_ERR_IO, false, _("Unable to generate output file from PPSUB.OUTPUT.JPEG2"));
+        psError(psErrorCodeLast(), false, _("Unable to generate output file from PPSUB.OUTPUT.JPEG2"));
         return false;
     }
     if (jpeg2->type != PM_FPA_FILE_JPEG) {
-        psError(PS_ERR_IO, true, "PPSUB.OUTPUT.JPEG2 is not of type JPEG");
+        psError(psErrorCodeLast(), true, "PPSUB.OUTPUT.JPEG2 is not of type JPEG");
         return false;
     }
@@ -338,9 +338,9 @@
     pmFPAfile *jpeg3 = pmFPAfileDefineOutput(config, NULL, "PPSUB.OUTPUT.RESID.JPEG");
     if (!jpeg3) {
-        psError(PS_ERR_IO, false, _("Unable to generate output file from PPSUB.OUTPUT.RESID.JPEG"));
+        psError(psErrorCodeLast(), false, _("Unable to generate output file from PPSUB.OUTPUT.RESID.JPEG"));
         return false;
     }
     if (jpeg3->type != PM_FPA_FILE_JPEG) {
-        psError(PS_ERR_IO, true, "PPSUB.OUTPUT.RESID.JPEG is not of type JPEG");
+        psError(psErrorCodeLast(), true, "PPSUB.OUTPUT.RESID.JPEG is not of type JPEG");
         return false;
     }
@@ -360,9 +360,9 @@
         pmFPAfile *psphot = pmFPAfileDefineFromFPA(config, output->fpa, 1, 1, "PSPHOT.INPUT");
         if (!psphot) {
-            psError(PS_ERR_IO, false, "Failed to build FPA from PSPHOT.INPUT");
+            psError(psErrorCodeLast(), false, "Failed to build FPA from PSPHOT.INPUT");
             return false;
         }
         if (psphot->type != PM_FPA_FILE_IMAGE) {
-            psError(PS_ERR_IO, true, "PSPHOT.INPUT is not of type IMAGE");
+            psError(psErrorCodeLast(), true, "PSPHOT.INPUT is not of type IMAGE");
             return false;
         }
@@ -374,9 +374,9 @@
         pmFPAfile *psf = pmFPAfileDefineFromFPA(config, output->fpa, 1, 1, "PSPHOT.PSF.LOAD");
         if (!psf) {
-            psError(PS_ERR_IO, false, "Failed to build FPA from PSPHOT.PSF.LOAD");
+            psError(psErrorCodeLast(), false, "Failed to build FPA from PSPHOT.PSF.LOAD");
             return false;
         }
         if (psf->type != PM_FPA_FILE_PSF) {
-            psError(PS_ERR_IO, true, "PSPHOT.PSF.LOAD is not of type PSF");
+            psError(psErrorCodeLast(), true, "PSPHOT.PSF.LOAD is not of type PSF");
             return false;
         }
@@ -384,5 +384,5 @@
 
         if (!psphotDefineFiles(config, psphot)) {
-            psError(PS_ERR_UNKNOWN, false, "Unable to set up psphot files.");
+            psError(psErrorCodeLast(), false, "Unable to set up psphot files.");
             return false;
         }
@@ -395,5 +395,5 @@
                                                  PM_FPA_FILE_CMF);
         if (!outSources) {
-            psError(PS_ERR_UNKNOWN, false, "Unable to set up output source file.");
+            psError(psErrorCodeLast(), false, "Unable to set up output source file.");
             return false;
         }
@@ -404,5 +404,5 @@
                                                      PM_FPA_FILE_CMF);
             if (!invSources) {
-                psError(PS_ERR_UNKNOWN, false, "Unable to set up inverse source file.");
+                psError(psErrorCodeLast(), false, "Unable to set up inverse source file.");
                 return false;
             }
Index: /trunk/ppSub/src/ppSubDefineOutput.c
===================================================================
--- /trunk/ppSub/src/ppSubDefineOutput.c	(revision 26981)
+++ /trunk/ppSub/src/ppSubDefineOutput.c	(revision 26982)
@@ -55,10 +55,10 @@
 
     if (!kernels) {
-	hdu = pmHDUFromCell(refConv->parent);
+        hdu = pmHDUFromCell(refConv->parent);
         analysis = refConv->analysis;
         kernels = psMetadataLookupPtr(&mdok, analysis, PM_SUBTRACTION_ANALYSIS_KERNEL);
     }
     if (!kernels) {
-        psError(PS_ERR_UNEXPECTED_NULL, true, "Unable to find SUBTRACTION.KERNEL");
+        psError(PPSUB_ERR_UNKNOWN, true, "Unable to find SUBTRACTION.KERNEL");
         psFree(outRO);
         return false;
Index: /trunk/ppSub/src/ppSubErrorCodes.dat
===================================================================
--- /trunk/ppSub/src/ppSubErrorCodes.dat	(revision 26981)
+++ /trunk/ppSub/src/ppSubErrorCodes.dat	(revision 26982)
@@ -10,2 +10,3 @@
 DATA                    Problem in data values
 NO_OVERLAP		No overlap between input and skycell
+PROG			Programming error
Index: /trunk/ppSub/src/ppSubLoop.c
===================================================================
--- /trunk/ppSub/src/ppSubLoop.c	(revision 26981)
+++ /trunk/ppSub/src/ppSubLoop.c	(revision 26982)
@@ -43,10 +43,10 @@
 
     if (!ppSubSetMasks(config)) {
-        psError(PS_ERR_UNKNOWN, false, "Unable to set masks.");
+        psError(psErrorCodeLast(), false, "Unable to set masks.");
         return false;
     }
 
     if (!ppSubMatchPSFs(data)) {
-        psError(PS_ERR_UNKNOWN, false, "Unable to match PSFs.");
+        psError(psErrorCodeLast(), false, "Unable to match PSFs.");
         return false;
     }
@@ -57,5 +57,5 @@
     // generate the residual stamp grid for visualization
     if (!ppSubResidualSampleJpeg(config)) {
-        psError(PS_ERR_UNKNOWN, false, "Unable to update.");
+        psError(psErrorCodeLast(), false, "Unable to update.");
         return false;
     }
@@ -71,5 +71,5 @@
 
     if (!ppSubLowThreshold(data)) {
-        psError(PS_ERR_UNKNOWN, false, "Unable to threshold images.");
+        psError(psErrorCodeLast(), false, "Unable to threshold images.");
         return false;
     }
@@ -82,15 +82,15 @@
 
     if (!ppSubDefineOutput("PPSUB.OUTPUT", config)) {
-        psError(PS_ERR_UNKNOWN, false, "Unable to define output.");
+        psError(psErrorCodeLast(), false, "Unable to define output.");
         return false;
     }
 
     if (!data->quality && !ppSubMakePSF(data)) {
-        psError(PS_ERR_UNKNOWN, false, "Unable to generate PSF.");
+        psError(psErrorCodeLast(), false, "Unable to generate PSF.");
         return false;
     }
 
     if (!ppSubReadoutSubtract(config)) {
-        psError(PS_ERR_UNKNOWN, false, "Unable to subtract images.");
+        psError(psErrorCodeLast(), false, "Unable to subtract images.");
         return false;
     }
@@ -104,5 +104,5 @@
     // Higher order background subtraction using psphot
     if (!ppSubBackground(config)) {
-        psError(PS_ERR_UNKNOWN, false, "Unable to subtract background.");
+        psError(psErrorCodeLast(), false, "Unable to subtract background.");
         return false;
     }
@@ -110,5 +110,5 @@
     // Perform Variance correction (rescale within a modest range)
     if (!ppSubVarianceRescale(config)) {
-        psError(PS_ERR_UNKNOWN, false, "Unable to rescale variance.");
+        psError(psErrorCodeLast(), false, "Unable to rescale variance.");
         return false;
     }
@@ -120,5 +120,5 @@
 
     if (!data->quality && !ppSubReadoutPhotometry("PPSUB.OUTPUT", data)) {
-        psError(PS_ERR_UNKNOWN, false, "Unable to perform photometry.");
+        psError(psErrorCodeLast(), false, "Unable to perform photometry.");
         return false;
     }
@@ -131,5 +131,5 @@
     // Perform statistics on the cell
     if (!ppSubReadoutStats(data)) {
-        psError(PS_ERR_UNKNOWN, false, "Unable to collect statistics");
+        psError(psErrorCodeLast(), false, "Unable to collect statistics");
         return false;
     }
@@ -137,5 +137,5 @@
     // generate the binned image used to write the jpeg
     if (!ppSubReadoutJpeg(config)) {
-        psError(PS_ERR_UNKNOWN, false, "Unable to update.");
+        psError(psErrorCodeLast(), false, "Unable to update.");
         return false;
     }
@@ -149,10 +149,10 @@
 
         if (data->inverse && !ppSubDefineOutput("PPSUB.INVERSE", config)) {
-            psError(PS_ERR_UNKNOWN, false, "Unable to define inverse.");
+            psError(psErrorCodeLast(), false, "Unable to define inverse.");
             return false;
         }
 
         if (!ppSubReadoutInverse(config)) {
-            psError(PS_ERR_UNKNOWN, false, "Unable to invert images.");
+            psError(psErrorCodeLast(), false, "Unable to invert images.");
             return false;
         }
@@ -170,5 +170,5 @@
 
         if (!data->quality && !ppSubReadoutPhotometry("PPSUB.INVERSE", data)) {
-            psError(PS_ERR_UNKNOWN, false, "Unable to perform photometry.");
+            psError(psErrorCodeLast(), false, "Unable to perform photometry.");
             return false;
         }
Index: /trunk/ppSub/src/ppSubMakePSF.c
===================================================================
--- /trunk/ppSub/src/ppSubMakePSF.c	(revision 26981)
+++ /trunk/ppSub/src/ppSubMakePSF.c	(revision 26982)
@@ -59,5 +59,5 @@
     pmFPAfile *photFile = psMetadataLookupPtr(&mdok, config->files, "PSPHOT.INPUT"); // Photometry file
     if (!pmFPACopy(photFile->fpa, minuendFile->fpa)) {
-        psError(PS_ERR_UNKNOWN, false, "Unable to copy FPA for photometry");
+        psError(PPSUB_ERR_CONFIG, false, "Unable to copy FPA for photometry");
         psFree(view);
         return false;
Index: /trunk/ppSub/src/ppSubMatchPSFs.c
===================================================================
--- /trunk/ppSub/src/ppSubMatchPSFs.c	(revision 26981)
+++ /trunk/ppSub/src/ppSubMatchPSFs.c	(revision 26982)
@@ -56,5 +56,5 @@
     psAssert(photFile, "Need photometry file.");
     if (!pmFPACopy(photFile->fpa, ro->parent->parent->parent)) {
-        psError(PS_ERR_UNKNOWN, false, "Unable to copy FPA for photometry");
+        psError(PPSUB_ERR_CONFIG, false, "Unable to copy FPA for photometry");
         return false;
     }
@@ -170,5 +170,5 @@
     if (!pmSubtractionParamsScale(kernelSize, stampSize, kernelWidths, inFWHM, refFWHM,
                                   scaleRef, scaleMin, scaleMax)) {
-        psError(PS_ERR_UNKNOWN, false, "Unable to scale parameters.");
+        psError(PPSUB_ERR_DATA, false, "Unable to scale parameters.");
         return false;
     }
@@ -236,5 +236,5 @@
         psFree(lists);
         if (!detections->allSources) {
-            psError(PS_ERR_UNKNOWN, false, "Unable to merge source lists");
+            psError(PPSUB_ERR_DATA, false, "Unable to merge source lists");
             psFree(detections);
             return false;
@@ -262,5 +262,5 @@
     pmSubtractionKernelsType type = pmSubtractionKernelsTypeFromString(typeStr); // Type of kernel
     if (type == PM_SUBTRACTION_KERNEL_NONE) {
-        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Unrecognised kernel type: %s", typeStr);
+        psError(PPSUB_ERR_ARGUMENTS, true, "Unrecognised kernel type: %s", typeStr);
         return false;
     }
@@ -319,5 +319,5 @@
             break;
           default:
-            psError(PS_ERR_BAD_PARAMETER_VALUE, false, "Invalid value for -convolve");
+            psError(PPSUB_ERR_ARGUMENTS, false, "Invalid value for -convolve");
             return false;
         }
@@ -325,5 +325,5 @@
 
     if (!subScaleKernel(data, widths, &size, &footprint)) {
-        psError(PS_ERR_UNKNOWN, false, "Unable to scale kernel parameters");
+        psError(PPSUB_ERR_DATA, false, "Unable to scale kernel parameters");
         return false;
     }
@@ -391,5 +391,5 @@
             return true;
         } else {
-            psError(PS_ERR_UNKNOWN, false, "Unable to match images.");
+            psError(PPSUB_ERR_DATA, false, "Unable to match images.");
             return false;
         }
Index: /trunk/ppSub/src/ppSubReadoutInverse.c
===================================================================
--- /trunk/ppSub/src/ppSubReadoutInverse.c	(revision 26981)
+++ /trunk/ppSub/src/ppSubReadoutInverse.c	(revision 26982)
@@ -34,10 +34,10 @@
     pmHDU *invHDU = invFPA->hdu;          // Inverse HDU
     if (!pmAstromWriteWCS(invHDU->header, outFPA, outChip, WCS_TOLERANCE)) {
-        psError(PS_ERR_UNKNOWN, false, "Unable to write WCS astrometry to PPSUB.INVERSE.");
+        psError(psErrorCodeLast(), false, "Unable to write WCS astrometry to PPSUB.INVERSE.");
         return false;
     }
     // Read from newly written astrometry so that it exists in the "inverse" FPA (for sources)
     if (!pmAstromReadWCS(invFPA, invChip, invHDU->header, 1.0)) {
-        psError(PS_ERR_UNKNOWN, false, "Unable to read WCS astrometry.");
+        psError(psErrorCodeLast(), false, "Unable to read WCS astrometry.");
         return false;
     }
Index: /trunk/ppSub/src/ppSubReadoutJpeg.c
===================================================================
--- /trunk/ppSub/src/ppSubReadoutJpeg.c	(revision 26981)
+++ /trunk/ppSub/src/ppSubReadoutJpeg.c	(revision 26982)
@@ -33,5 +33,5 @@
     pmReadout *ro1 = pmReadoutAlloc(cell1), *ro2 = pmReadoutAlloc(cell2); // Binned readouts
     if (!pmReadoutRebin(ro1, outRO, maskBad, bin1, bin1)) {
-        psError(PS_ERR_UNKNOWN, false, "Unable to bin output (1st binning)");
+        psError(PPSUB_ERR_DATA, false, "Unable to bin output (1st binning)");
         psFree(ro1);
         psFree(ro2);
@@ -39,5 +39,5 @@
     }
     if (!pmReadoutRebin(ro2, ro1, 0, bin2, bin2)) {
-        psError(PS_ERR_UNKNOWN, false, "Unable to bin output (2nd binning)");
+        psError(PPSUB_ERR_DATA, false, "Unable to bin output (2nd binning)");
         psFree(ro1);
         psFree(ro2);
Index: /trunk/ppSub/src/ppSubReadoutPhotometry.c
===================================================================
--- /trunk/ppSub/src/ppSubReadoutPhotometry.c	(revision 26981)
+++ /trunk/ppSub/src/ppSubReadoutPhotometry.c	(revision 26982)
@@ -53,5 +53,5 @@
     pmFPAfile *inFile = psMetadataLookupPtr(&mdok, config->files, name); // Input file
     if (!pmFPACopy(photFile->fpa, inFile->fpa)) {
-        psError(PS_ERR_UNKNOWN, false, "Unable to copy FPA for photometry");
+        psError(PPSUB_ERR_CONFIG, false, "Unable to copy FPA for photometry");
         psFree(view);
         return false;
@@ -111,13 +111,13 @@
     if (!data->quality) {
         if (!psMetadataCopySingle(inRO->analysis, photRO->analysis, "PSPHOT.DETECTIONS")) {
-            psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to copy PSPHOT.DETECTIONS");
+            psError(PPSUB_ERR_PROG, false, "Unable to copy PSPHOT.DETECTIONS");
             return false;
         }
         if (!psMetadataCopySingle(inRO->analysis, photRO->analysis, "PSPHOT.HEADER")) {
-            psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to copy PSPHOT.HEADER");
+            psError(PPSUB_ERR_PROG, false, "Unable to copy PSPHOT.HEADER");
             return false;
         }
         if (!psMetadataCopySingle(inRO->analysis, photRO->analysis, PM_DETEFF_ANALYSIS)) {
-            psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to copy Detection Efficiency");
+            psError(PPSUB_ERR_PROG, false, "Unable to copy Detection Efficiency");
             return false;
         }
Index: /trunk/ppSub/src/ppSubReadoutStats.c
===================================================================
--- /trunk/ppSub/src/ppSubReadoutStats.c	(revision 26981)
+++ /trunk/ppSub/src/ppSubReadoutStats.c	(revision 26982)
@@ -23,5 +23,5 @@
     pmFPAfile *output = psMetadataLookupPtr(NULL, config->files, "PPSUB.OUTPUT"); // Output file
     if (!output) {
-        psError(PS_ERR_UNEXPECTED_NULL, true, "Unable to find file PPSUB.OUTPUT.\n");
+        psError(PPSUB_ERR_PROG, true, "Unable to find file PPSUB.OUTPUT.\n");
         return false;
     }
Index: /trunk/ppSub/src/ppSubReadoutSubtract.c
===================================================================
--- /trunk/ppSub/src/ppSubReadoutSubtract.c	(revision 26981)
+++ /trunk/ppSub/src/ppSubReadoutSubtract.c	(revision 26982)
@@ -71,5 +71,5 @@
     pmFPA *outFPA = outFile->fpa;       // Output FPA
     if (!pmConceptsCopyFPA(outFPA, inFPA, true, true)) {
-        psError(PS_ERR_UNKNOWN, false, "Unable to copy concepts from input to output.");
+        psError(PPSUB_ERR_CONFIG, false, "Unable to copy concepts from input to output.");
         psFree(outRO);
         psFree(view);
@@ -84,13 +84,13 @@
     psFree(view);
     if (!outHDU || !inHDU) {
-        psError(PS_ERR_UNKNOWN, false, "Unable to find HDU at FPA level to copy astrometry.");
+        psError(PPSUB_ERR_PROG, true, "Unable to find HDU at FPA level to copy astrometry.");
         return false;
     }
     if (!pmAstromReadWCS(outFPA, outChip, inHDU->header, 1.0)) {
-        psError(PS_ERR_UNKNOWN, false, "Unable to read WCS astrometry from input FPA.");
+        psError(psErrorCodeLast(), false, "Unable to read WCS astrometry from input FPA.");
         return false;
     }
     if (!pmAstromWriteWCS(outHDU->header, outFPA, outChip, WCS_TOLERANCE)) {
-        psError(PS_ERR_UNKNOWN, false, "Unable to write WCS astrometry to output FPA.");
+        psError(psErrorCodeLast(), false, "Unable to write WCS astrometry to output FPA.");
         return false;
     }
Index: /trunk/ppSub/src/ppSubSetMasks.c
===================================================================
--- /trunk/ppSub/src/ppSubSetMasks.c	(revision 26981)
+++ /trunk/ppSub/src/ppSubSetMasks.c	(revision 26982)
@@ -28,10 +28,10 @@
     psImageMaskType maskValue, markValue; // Mask values
     if (!pmConfigMaskSetBits(&maskValue, &markValue, config)) {
-        psError(PS_ERR_UNKNOWN, false, "Unable to determine mask value.");
+        psError(PPSUB_ERR_CONFIG, false, "Unable to determine mask value.");
         return false;
     }
 
     // Set the mask bits needed by psphot (in psphot recipe)
-    psphotSetMaskRecipe (config, maskValue, markValue);
+    psphotSetMaskRecipe(config, maskValue, markValue);
 
     // Look up recipe values
@@ -79,9 +79,9 @@
     // Mask the NAN values
     if (!pmReadoutMaskNonfinite(inRO, satValue)) {
-        psError(PS_ERR_UNKNOWN, false, "Unable to mask non-finite pixels in input.");
+        psError(PPSUB_ERR_DATA, false, "Unable to mask non-finite pixels in input.");
         return false;
     }
     if (!pmReadoutMaskNonfinite(refRO, satValue)) {
-        psError(PS_ERR_UNKNOWN, false, "Unable to mask non-finite pixels in reference.");
+        psError(PPSUB_ERR_DATA, false, "Unable to mask non-finite pixels in reference.");
         return false;
     }
@@ -94,5 +94,5 @@
     psImageInterpolateMode interpMode = psImageInterpolateModeFromString(interpModeStr); // Interp
     if (interpMode == PS_INTERPOLATE_NONE) {
-        psError(PS_ERR_BAD_PARAMETER_VALUE, false, "Unknown interpolation mode: %s", interpModeStr);
+        psError(PPSUB_ERR_CONFIG, false, "Unknown interpolation mode: %s", interpModeStr);
         return false;
     }
@@ -104,9 +104,9 @@
     // Interpolate over bad pixels, so the bad pixels don't explode
     if (!pmReadoutInterpolateBadPixels(inRO, maskVal, interpMode, poorFrac, maskPoor, maskBad)) {
-        psError(PS_ERR_UNKNOWN, false, "Unable to interpolate bad pixels for input image.");
+        psError(PPSUB_ERR_DATA, false, "Unable to interpolate bad pixels for input image.");
         return false;
     }
     if (!pmReadoutInterpolateBadPixels(refRO, maskVal, interpMode, poorFrac, maskPoor, maskBad)) {
-        psError(PS_ERR_UNKNOWN, false, "Unable to interpolate bad pixels for reference image.");
+        psError(PPSUB_ERR_DATA, false, "Unable to interpolate bad pixels for reference image.");
         return false;
     }
Index: /trunk/ppSub/src/ppSubThreshold.c
===================================================================
--- /trunk/ppSub/src/ppSubThreshold.c	(revision 26981)
+++ /trunk/ppSub/src/ppSubThreshold.c	(revision 26982)
@@ -45,5 +45,5 @@
     psRandom *rng = psRandomAlloc(PS_RANDOM_TAUS);                               // Random number generator
     if (!psImageBackground(stats, NULL, subImage, subMask, maskIgnore, rng)) {
-        psError(PS_ERR_UNKNOWN, false, "Unable to determine threshold.");
+        psError(PPSUB_ERR_DATA, false, "Unable to determine threshold.");
         psFree(rng);
         psFree(stats);
@@ -97,5 +97,5 @@
     pmReadout *in = pmFPAfileThisReadout(config->files, view, "PPSUB.INPUT.CONV"); // Input image
     if (!in) {
-        psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to find readout.");
+        psError(PPSUB_ERR_UNKNOWN, false, "Unable to find readout.");
         return false;
     }
@@ -103,5 +103,5 @@
     pmReadout *ref = pmFPAfileThisReadout(config->files, view, "PPSUB.REF.CONV"); // Reference image
     if (!ref) {
-        psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to find readout.");
+        psError(PPSUB_ERR_UNKNOWN, false, "Unable to find readout.");
         return false;
     }
@@ -114,9 +114,9 @@
         psRegion *region = regItem->data.V; // Region of interest
         if (!lowThreshold(in, thresh, maskVal, maskThresh, region, "input convolved image")) {
-            psError(PS_ERR_UNKNOWN, false, "Unable to threshold input image.");
+            psError(psErrorCodeLast(), false, "Unable to threshold input image.");
             return false;
         }
         if (!lowThreshold(ref, thresh, maskVal, maskThresh, region, "reference convolved image")) {
-            psError(PS_ERR_UNKNOWN, false, "Unable to threshold input image.");
+            psError(psErrorCodeLast(), false, "Unable to threshold input image.");
             return false;
         }
Index: /trunk/ppSub/src/ppSubVarianceRescale.c
===================================================================
--- /trunk/ppSub/src/ppSubVarianceRescale.c	(revision 26981)
+++ /trunk/ppSub/src/ppSubVarianceRescale.c	(revision 26982)
@@ -35,15 +35,15 @@
     int num = psMetadataLookupS32(&mdok, recipe, "RENORM.NUM");
     if (!mdok) {
-        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "RENORM.NUM is not set in the recipe");
+        psError(PPSUB_ERR_ARGUMENTS, true, "RENORM.NUM is not set in the recipe");
         return false;
     }
     float minValid = psMetadataLookupF32(&mdok, recipe, "RENORM.MIN");
     if (!mdok) {
-        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "RENORM.MIN is not set in the recipe");
+        psError(PPSUB_ERR_ARGUMENTS, true, "RENORM.MIN is not set in the recipe");
         return false;
     }
     float maxValid = psMetadataLookupF32(&mdok, recipe, "RENORM.MAX");
     if (!mdok) {
-        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "RENORM.MAX is not set in the recipe");
+        psError(PPSUB_ERR_ARGUMENTS, true, "RENORM.MAX is not set in the recipe");
         return false;
     }
