Study guide
7.4 Identifying Logic Errors with the PUTLOG Statement
SAS Certified Specialist: Base Programming Using SAS 9.4 A00-231
Track your progress as you read
Finished sections get a check mark.
1 Chapter 1: SAS Base Programming Exam Overview
1.1 A00-231 Exam Format, Scoring & Test-Day Logistics 1.2 Official Content Areas, Weights & Study Plan
2 Chapter 2: Accessing & Creating SAS Data Structures
2.1 SAS Environment, Syntax Rules, & Data Step Basics 2.2 SAS Data Libraries & the LIBNAME Statement 2.3 Investigating Libraries with PROC CONTENTS & PROC DATASETS 2.4 Importing Delimited & Excel Data with PROC IMPORT 2.5 Raw Data Ingestion with INFILE and INPUT Statements
3 Chapter 3: Managing & Combining SAS Data Sets
3.1 Reading SAS Data Sets with the SET Statement 3.2 Combining Data Sets: Concatenating & Interleaving 3.3 Match-Merging with BY Statements & FIRST./LAST. Processing 3.4 Controlling Data Output & Variable Selection (KEEP, DROP, RENAME, OBS=)
4 Chapter 4: Data Transformation & Conditional Logic
4.1 Creating & Modifying Variables with Assignment Statements 4.2 Modifying Variable Attributes with LENGTH, LABEL, FORMAT & RENAME= 4.3 Conditional Processing: IF-THEN/ELSE Statements & WHERE Subsetting 4.4 Accumulating Totals & Subtotals (RETAIN & Sum Statement) 4.5 Processing Data Iteratively with DO Loops
5 Chapter 5: SAS Functions & Data Type Conversions
5.1 Character Functions for String Manipulation 5.2 Numeric & Mathematical Functions 5.3 Working with SAS Dates, Times, & Intervals 5.4 Reading & Displaying Dates with Informats and Formats 5.5 Explicit & Implicit Data Type Conversions (INPUT & PUT)
6 Chapter 6: Restructuring Data & Program Maintenance
6.1 SAS Array Processing for Multi-Variable Transformations 6.2 Sorting Data Sets with PROC SORT 6.3 Restructuring Data Sets with PROC TRANSPOSE 6.4 Creating & Applying Custom Formats with PROC FORMAT 6.5 Simplifying Programs with Macro Variables (%LET)
7 Chapter 7: Error Handling & Debugging SAS Programs
7.1 SAS Log Analysis & Diagnostic Messages 7.2 Syntax vs. Logic Errors & Phasing 7.3 Debugging Techniques with _ERROR_, _N_, & PUT Statements 7.4 Identifying Logic Errors with the PUTLOG Statement 7.5 Handling Missing Values & Preventing Calculation Propagations
8 Chapter 8: Summary & Detail Data Reporting
8.1 Detail Reporting with PROC PRINT 8.2 Descriptive Statistics with PROC MEANS & PROC SUMMARY 8.3 Frequency & Categorical Analysis with PROC FREQ 8.4 Screening Extreme & Missing Values with PROC UNIVARIATE 8.5 Custom Tabular Reports with PROC REPORT & PROC TABULATE
9 Chapter 9: ODS Output Delivery & Data Export
9.1 Output Delivery System (ODS) Architecture Basics 9.2 Generating PDF, HTML, & RTF Output Destinations 9.3 Exporting Reports to Excel with ODS EXCEL & XLSX 9.4 Generating CSV, PowerPoint & Other ODS Destinations 9.5 Customizing ODS Titles, Footnotes, & Global Options 9.6 Exporting SAS Data Sets with PROC EXPORT & the XLSX Engine
7.4 Identifying Logic Errors with the PUTLOG Statement
Key Takeaways Explain This Topic AI
PUTLOG always writes to the SAS log, even when a FILE statement has redirected PUT output to an external file, which is why it is the exam's designated debugging statement.
PUTLOG variable= uses named output, printing the variable name, an equal sign, and the current PDV value.
PUTLOG ALL dumps every PDV variable including the automatic N and ERROR values.
Wrapping PUTLOG in conditional logic such as if ERROR then keeps the log readable on large data sets.
Prefixing the text with WARNING: or ERROR: makes SAS colour the line in the log, so custom diagnostics stand out.
Last updated: August 2026
7.4 Identifying Logic Errors with the PUTLOG Statement
Quick Answer: PUTLOG writes text and variable values to the SAS log , and it does so unconditionally — even when a FILE statement has redirected ordinary PUT output somewhere else. The A00-231 content guide names it in three of the four expanded objectives under "Identify and resolve programming logic errors": use PUTLOG to help identify logic errors, use PUTLOG to write the value of a variable, formatted values, or all variables, and use PUTLOG with conditional logic.
A logic error is a program that runs cleanly and produces the wrong answer. No ERROR: appears, no WARNING: appears, and the observation count looks plausible. The only way to find one is to make the DATA step tell you what it is holding at the moment it goes wrong, and PUTLOG is the statement built for that job.
1. Why PUTLOG and Not PUT?
Both statements can write to the log. They diverge the moment the DATA step also writes an external file. data _null_;
- set work.transactions;
- file "C:\output\extract.txt"; /* PUT output is now redirected */
- put ClientID Amount; /* goes to extract.txt */
- putlog "Row " _n_ " ClientID=" ClientID; /* still goes to the LOG */
- run;
- Statement Destination
- PUT The SAS log only if no FILE statement is active; otherwise the external file
- PUTLOG Always the SAS log, regardless of any FILE statement
That guarantee is the whole point. In a step that writes a flat file, a plain PUT diagnostic silently pollutes the output file instead of appearing in the log — a debugging statement that corrupts the deliverable.
2. Writing Variable Values: Named Output
Appending an equal sign to a variable name produces named output : the variable name, an equal sign, and the current value. data work.audit;
- set work.claims;
- Ratio = Payout / ClaimAmount;
- putlog ClaimID= ClaimAmount= Payout= Ratio=;
- run;
- SAS Log Output: ClaimID=A1043 ClaimAmount=12000 Payout=9000 Ratio=0.75
- ClaimID=A1044 ClaimAmount=8000 Payout=8600 Ratio=1.075
Named output beats bare putlog Ratio; because the label travels with the value. When ten variables scroll past, Ratio=1.075 is self-describing while a naked 1.075 is not.
- Formatted Values
- Place a format after the variable to control how the value prints in the log. data work.formatted_log;
- set work.orders;
putlog "Order " OrderID= " placed " OrderDate date9.
- " for " Amount dollar12.2;
- run;
- SAS Log Output: Order OrderID=88213 placed 31OCT2026 for $1,250.75
This matters when debugging dates: an unformatted SAS date prints as 24775 , which tells you nothing about whether the date logic is right.
- 3. Dumping the Whole PDV: PUTLOG ALL data work.debug_all;
- set work.sales_raw;
- Bonus = Sales * 0.05;
- if _n_ = 1 then putlog "=== PDV AT FIRST OBSERVATION ===" / _ALL_;
- run;
- SAS Log Output: === PDV AT FIRST OBSERVATION ===
- RepID=101 Region=East Sales=5000 Bonus=250 _ERROR_=0 _N_=1
_ALL_ prints every variable currently in the PDV, including the automatic _N_ and _ERROR_ , and including variables that a DROP statement will remove before the row is written. That last detail makes it the fastest way to inspect intermediate values you deliberately excluded from the output data set.
Exam Tip: the forward slash ( / ) in a PUT or PUTLOG statement is a line-pointer control that moves output
to the next line of the log. It is how a single statement produces a heading followed by a dump.
4. PUTLOG with Conditional Logic
An unconditional PUTLOG on a ten-million-row data set produces ten million log lines. Real debugging is conditional. data work.processed_claims;
- set work.medical_claims;
- Ratio = Payout / ClaimAmount;
- /* Fire only when something is actually wrong */
- if _ERROR_ = 1 or Ratio > 1 or missing(ClaimAmount) then do;
- putlog "WARNING: Suspect claim at observation " _n_;
- putlog ClaimID= ClaimAmount= Payout= Ratio= _ERROR_=;
- end;
- run;
Three conditional patterns cover almost every debugging need:
- Pattern Code Use
- First n rows if _n_ <= 5 then putlog _all_; Confirm the shape of the data before trusting the logic
- Error rows only if _ERROR_ then putlog _all_; Catch invalid data and failed conversions
- Business-rule breach if Ratio > 1 then putlog ClaimID= Ratio=; Find rows that pass syntax but violate the rule
- Colouring Your Messages
The SAS log colours any line beginning with WARNING: or ERROR: . Because PUTLOG writes raw text, starting the message with one of those tokens makes a custom diagnostic as visually prominent as a SAS-generated one. putlog "ERROR: Payout exceeds claim amount for " ClaimID=; /* red in the log */
- putlog "WARNING: Missing claim amount at obs " _n_; /* highlighted in the log */
- putlog "NOTE: Row processed normally"; /* ordinary note styling */
This does not set _ERROR_ , halt the step, or change the return code. It only changes how the line is rendered — useful for a human reading a 5,000-line batch log, and a favourite exam distractor for candidates who assume the prefix has functional meaning.
- 5. A Complete Debugging Workflow data work.commission;
- set work.sales;
- /* 1. Confirm the incoming values on the first few rows */
- if _n_ <= 3 then putlog "INPUT >> " _all_;
- /* 2. The suspect calculation */
- if Units > 0 then Rate = Revenue / Units;
- else Rate = 0;
- Commission = Rate * 0.08;
- /* 3. Trace the branch that was actually taken */
- if Units <= 0 then
- putlog "WARNING: Non-positive Units, Rate forced to 0 at obs " _n_ " " RepID=;
- /* 4. Flag results that violate the business rule */
- if Commission > 10000 then
- putlog "ERROR: Implausible commission " Commission dollar12.2 " for " RepID=;
- run;
The sequence is always the same: verify the input, expose the branch, then test the output against a rule you can state in one sentence. PUTLOG is what makes each of those three steps visible.