23

SAS likes to continue processing well after warnings and errors, so I often need to scroll back through pages in the log to find an issue. Is there a better way? I'd like it to stop as soon as the first error or warning appears so I can fix it and try again.

Two Bit Gangster
  • 973
  • 2
  • 9
  • 14

5 Answers5

17

The ERRORS=1 option was previously suggested, but that only stops he ERROR messages from writing to the log. I would suggest another system option ERRORABEND which will stop the program from further processing for most errors. I don't know of an option to terminate processing due to warnings, but I think that you could add a macro like the following to stop processing.

%macro check_for_errors;
   %if &syserr > 0 %then %do;
      endsas;
   %end;
%mend check_for_errors;

data test1;
    <data step code>
run;
%check_for_errors;

You could repeat the macro call after each step of your program, and it should terminate at the point that the error code is anything but 0.

Jay Corbett
  • 28,091
  • 21
  • 57
  • 74
RWill
  • 939
  • 5
  • 6
  • 1
    Should have read more about the ERRORS= option...removed my answer and updated your answer – Jay Corbett Jan 26 '12 at 03:10
  • 3
    Is there something like the ERRORABEND option that doesn't cause disconnection to the SAS server? I use EG connected to an external unix server and while it would be great to stop processing at the first error, ERRORABEND closes the connection to the server which takes a while to reestablish on the next run. – o.h Jan 26 '12 at 15:53
  • 1
    You might also check if `&syserrortext` is non-empty. I find that this variable is set more reliably than `&syserr`. – Jake Z Aug 22 '14 at 17:00
5

I've been using the %runquit macro recently. Works well for both batch jobs and interactive sessions (doesn't close your session, just stops running the code).

Source: http://www.cpc.unc.edu/research/tools/data_analysis/sas_to_stata/sas-macros/runquit.html

To use it you basically type %runquit; at the end of any data step or PROC instead of typing your regular run or quit statement.

Code:

%macro runquit;
  ; run; quit;
  %if &syserr. ne 0 %then %do;
     %abort cancel;
  %end;
%mend runquit;

Datastep usage:

data something; 
 * do some stuff;
%runquit;

PROC usage:

proc sql; 
  * do some stuff;
%runquit;

It's not quite as pretty when reading through code, but it does make debugging a lot easier.

Robert Penridge
  • 8,424
  • 2
  • 34
  • 55
  • This seemed like a good answer but it just stalls Enterprise Guide. `Running.... running....` and never completes to return a result/error to the log. It will stop the program barging on and overwriting/creating other datasets, so it fulfils the main purpose I suppose. – thelatemail Sep 06 '18 at 23:22
  • @thelatemail We are migrating to an environment where I'll be able to test this out with EG. Will update once I've had a chance to test. – Robert Penridge Sep 10 '18 at 15:49
3

One option is to replace run with run &g_cancel throughout, and proc sql; with proc sql &g_noexec;. Initially &g_cancel and &g_noexec are set to nothing so everything runs.

On hitting an error (either %sys_rc, %sql_rc or using referring to business logic) set &g_cancel to cancel and &g_noexec to noexec.

This should stop any subsequent steps from running - obviously the macro variables can be omitted for steps that have to run regardless (for instance a tidy up) or checked before performing steps purely in macro.

Note for Enterprise Guide users: The only warning note is that if you are running multiple code items in the same session you will need to reset the error terms at the start of each code item, lest unrelated errors stop anything working.

Bendy
  • 3,506
  • 6
  • 40
  • 71
syntheticbrain
  • 288
  • 2
  • 13
2

As complement to Rwill's answer:

If you are using a stored process (STP), it's also nice to not show the log to your users when an error occurs and to remove the "Show SAS log" button.

That can be achieved with this

%macro checkcc;
    options obs=max no$syntaxcheck;
    %if (&syscc gt 4) %then
        %do;
            data _null_;
                file _webout;
                put "<h3>Sorry, your request was not processed successfully.<h3>";
                rc = stpsrvset('program error', 0);
            run;
        %end;
    %let syscc=0;
%mend checkcc;
%checkcc;

source : http://support.sas.com/kb/16/225.html

And here is an enhanced version that I made to still show the error in json format.

%macro checkErrors;
    options obs=max no$syntaxcheck;
    %let old = %sysfunc(stpsrv_header(Content-type, application/json%str(;) charset=utf-8));
    %put &=syscc; %put &=syserr; %put &=sysrc; %put &=syswarningtext; %put &=syserrortext;
    %if (&syscc gt 4) %then %do;
        data _null_;
            file _webout;
            put '{';
            put '  "success":"false"';
            put '  ,"message":"' "&syserrortext" '"';
            put '  ,"syscc":"' "&syscc" '"';
            put '}';
            rc = stpsrvset('program error', 0);
            run;
        %end;
    %let syscc=0;
%mend checkErrors;
%checkErrors;

and HTML version :

%macro checkErrors_HTML;
    options obs=max no$syntaxcheck;
    %if (&syscc gt 4) %then %do;
        data _null_;
            file _webout;
            put '<!doctype html> ';
            put '<html> ';
            put '   <head> ';
            put '       <title>Error</title> ';
            put '   </head> ';
            put '   <body> ';
            put '       <h1>An Error Occured</h1>';
            put '       <p>' "&syserrortext" '</>';
            put '   </body>';
            put '</html>';
            rc = stpsrvset('program error', 0);
            run;
        %end;
    %let syscc=0;
%mend checkErrors_HTML;
%checkErrors_HTML;
stallingOne
  • 3,633
  • 3
  • 41
  • 63
  • Very nice! Presumably you'd also want a `%abort` or `endsas;` in there, so the rest of the program does not run unnecessarily? – Allan Bowe Aug 26 '17 at 08:17
  • @AllanBowe Wouldn't this require to `%checkErrors` very often in your program? I'm just placing `%checkErrors` at the very end of the STP, so I'm not sure it would be useful to abort anymore. What do you think? – stallingOne Aug 29 '17 at 08:16
  • correct, if at the end of the program then no need for abort. Am just thinking in terms of some of my own use cases (long running STPs) where it would be handy to be able to abort in the middle of a program without sending errors to the client. – Allan Bowe Aug 29 '17 at 09:20
  • discovered today - the `syscc=0` part is very much necessary! – Allan Bowe Sep 22 '18 at 17:35
2

I frequently do something similar to RWill, but I wrap my entire program in a macro. After each DATA step, PROC SQL, PROC SORT, etc. I check for an error code (&SYSERR or &SQLRC). If it is non-zero, I jump to the end.

More details and code here: https://heuristically.wordpress.com/2012/02/09/return-codes-errors-sas/

I cannot use RWill's endsas because of how our organization's batch system runs independent programs in one SAS session.

Andrew
  • 1,619
  • 3
  • 19
  • 24
  • 1
    This is great! Just read the blog entry and am trying it out. For years, I have been dumbfounded that SAS does not work this way automatically. Quick question: do I HAVE to use the SQLRC variable when checking for PROC SQL errors, or is that only if I care about recovering the SQL error code? It looks like SYSERR works with PROC SQL as well but I wanted to double check. Thanks again! – sparc_spread Jan 28 '13 at 15:24
  • 1
    @sparc_spread: If you do not care about handling the error in PROC SQL, then don't check the error code. One case where I can think this may be useful is using `drop table foo;` and you don't care whether the table exists. – Andrew Jan 28 '13 at 19:31