Skip to content

Part 14 — Troubleshooting

14.1 Overview

This section provides solutions to common issues encountered when using the PLI Platform. Issues are organized by component (Compiler, Runtime, Manifold, EBP) and include symptoms, causes, and solutions.


14.2 Compiler Issues

14.2.1 Compilation Errors

"Undefined variable: VARIABLE_NAME"

Symptom:

E:001 MYPROG.pli(45,10): Undefined variable 'CUSTOMER_ID'

Causes: - Variable not declared - Variable declared in different scope - Typo in variable name (PL/I is case-insensitive, but check spelling) - Missing %INCLUDE directive

Solutions:

/* Solution 1: Add DCL statement */
DCL CUSTOMER_ID CHAR(10);

/* Solution 2: Include copybook with declaration */
%INCLUDE CUSTDEF;

/* Solution 3: Check scope - declare at correct level */
PROC: PROCEDURE;
  DCL CUSTOMER_ID CHAR(10);  /* Declare before use */
  CUSTOMER_ID = 'C001';
END PROC;


"Syntax error near: token"

Symptom:

E:002 MYPROG.pli(52,20): Syntax error near 'END'

Causes: - Missing semicolon - Unmatched parentheses or quotes - Incorrect statement structure - Column margin issue (code outside columns 2-72)

Solutions:

/* Check semicolons */
DCL NAME CHAR(30);  /* ← Semicolon required */

/* Check parentheses */
IF (STATUS = 'A') THEN  /* Parentheses balanced */
  PUT SKIP LIST('Active');

/* Check margins - ensure code is in columns 2-72 */

Verify margins:

java -jar pli_compiler2.jar --source MYPROG.pli --margins 2,72


"Type mismatch: expected TYPE1, found TYPE2"

Symptom:

E:003 MYPROG.pli(67,15): Type mismatch: expected CHAR, found FIXED BIN

Causes: - Assigning incompatible types - Function returns wrong type - Missing type conversion

Solutions:

/* Use explicit conversion */
DCL AMOUNT DEC FIXED(15,2);
DCL COUNT FIXED BIN(31);

AMOUNT = COUNT;  /* Error: type mismatch */
AMOUNT = FIXED(COUNT, 15, 2);  /* Correct: explicit conversion */

/* Or use built-in conversion functions */
AMOUNT = DECIMAL(COUNT, 15, 2);


"%INCLUDE file not found"

Symptom:

E:004 MYPROG.pli(12,1): Include file not found: 'CUSTDEF.pli'

Causes: - File doesn't exist - Incorrect include path - Wrong file extension

Solutions:

# Specify include paths
java -jar pli_compiler2.jar \
  --source MYPROG.pli \
  --include /path/to/copybooks \
  --include /path/to/common

# Or set environment variable
export PLI_INCLUDE_PATH=/path/to/copybooks:/path/to/common

Verify file exists:

ls -la /path/to/copybooks/CUSTDEF.pli


"Circular include detected"

Symptom:

E:005 MYPROG.pli(10,1): Circular include detected: FILEA.pli → FILEB.pli → FILEA.pli

Cause: Include files reference each other circularly.

Solution: Restructure includes to break the circular dependency:

Before (circular):
FILEA.pli includes FILEB.pli
FILEB.pli includes FILEA.pli

After (fixed):
COMMON.pli ← common definitions
FILEA.pli includes COMMON.pli
FILEB.pli includes COMMON.pli

14.2.2 SQL Compilation Issues

"EXEC SQL not recognized"

Symptom: SQL statements are not transpiled, treated as syntax errors.

Cause: SQL support not enabled.

Solution:

java -jar pli_compiler2.jar \
  --source MYPROG.pli \
  --sql  # ← Enable SQL support


"Invalid SQL syntax in EXEC SQL block"

Symptom:

E:010 MYPROG.pli(120,5): Invalid SQL syntax

Causes: - Unsupported SQL statement - Incorrect host variable syntax - Missing terminator (;)

Solutions:

/* Correct host variable syntax */
EXEC SQL
  SELECT NAME, BALANCE
  INTO :CUSTOMER_NAME, :CUSTOMER_BALANCE  /* ← Colon prefix */
  FROM CUSTOMERS
  WHERE CUSTOMER_ID = :CUSTOMER_ID;

/* Ensure statement ends with semicolon */
EXEC SQL COMMIT;  /* ← Semicolon required */


14.2.3 CICS Compilation Issues

"EXEC CICS not recognized"

Symptom: CICS commands are not transpiled.

Cause: CICS support not enabled.

Solution:

java -jar pli_compiler2.jar \
  --source MYPROG.pli \
  --cics  # ← Enable CICS support
  --strategy instance  # ← Use instance strategy for CICS


"Unsupported EXEC CICS command"

Symptom:

E:020 MYPROG.pli(85,1): Unsupported CICS command: EXEC CICS SYNCPOINT

Cause: CICS command not yet implemented in compiler.

Solutions: - Check if alternative command exists (e.g., use COMMIT instead of SYNCPOINT) - Contact Heirloom support for roadmap - Use Helper system to override with custom Java code


14.2.4 Helper System Issues

"Helper JSON syntax error"

Symptom:

E:030 Helper configuration error: Unexpected token at line 15

Cause: Invalid JSON syntax in helper file.

Solution: Validate JSON:

# Use jq to validate
jq . helper.json

# Or use online JSON validator

Common JSON errors:

{
  "helpers": [
    {
      "program": "MYPROG",
      "variable": "CUSTOMER_NAME",
      "replaceWith": "customName"  // ← No trailing comma on last item
    }
  ]
}


14.3 Runtime Issues

14.3.1 Execution Errors

"NullPointerException in Group.getValue()"

Symptom:

java.lang.NullPointerException
  at heirloom.Group.getValue(Group.java:245)

Causes: - Group not initialized - Nested structure not instantiated - Accessing field before initialization

Solutions:

// Solution 1: Initialize Group before use
CUSTOMER_REC CUSTOMER = new CUSTOMER_REC();
CUSTOMER.ADDRESS = new CUSTOMER_REC.ADDRESS();  // ← Initialize nested

// Solution 2: Check for null before access
if (CUSTOMER != null && CUSTOMER.ADDRESS != null) {
    String city = CUSTOMER.ADDRESS.getCity();
}


"ClassCastException: Cannot cast to PLIString"

Symptom:

java.lang.ClassCastException: java.lang.String cannot be cast to heirloom.PLIString

Cause: Type mismatch between generated code and runtime expectations.

Solutions:

/* Ensure correct type annotations in PL/I */
DCL CUSTOMER_NAME CHAR(30);  /* Generates PLIString */

/* Or use --types primitive for String */

Recompile with correct type system:

java -jar pli_compiler2.jar \
  --source MYPROG.pli \
  --types manifold  # Use manifold type system


"ArrayIndexOutOfBoundsException"

Symptom:

java.lang.ArrayIndexOutOfBoundsException: Index 5 out of bounds for length 5

Cause: PL/I uses 1-based indexing, Java uses 0-based. Array access error.

Solutions:

/* PL/I arrays are 1-based */
DCL ITEMS(10) CHAR(20);  /* Indices 1-10, not 0-9 */

DO I = 1 TO 10;  /* Correct: 1-based loop */
  ITEMS(I) = 'VALUE';
END;

/* Not: DO I = 0 TO 9; ← Wrong! */


14.3.2 SQL Runtime Issues

"SQLException: Connection not established"

Symptom:

java.sql.SQLException: No suitable driver found for jdbc:db2://...

Causes: - JDBC driver not in classpath - Incorrect connection URL - Database not running

Solutions:

# Add JDBC driver to classpath (Gradle)
dependencies {
    runtimeOnly 'com.ibm.db2:jcc:11.5.8.0'
}

# Check connection configuration
# File: config/pli.properties
jdbc.url=jdbc:db2://localhost:50000/CUSTDB
jdbc.username=db2admin
jdbc.password=password
jdbc.driver=com.ibm.db2.jcc.DB2Driver

Test connection:

// Test JDBC connection
java -cp "lib/*:." TestConnection jdbc:db2://localhost:50000/CUSTDB


"SQLCODE -803: Duplicate key error"

Symptom:

SQL Error: SQLCODE=-803, SQLSTATE=23505
Duplicate key value in unique index

Cause: Attempting to insert duplicate primary key.

Solutions:

/* Check if record exists before insert */
EXEC SQL
  SELECT COUNT(*)
  INTO :RECORD_COUNT
  FROM CUSTOMERS
  WHERE CUSTOMER_ID = :CUSTOMER_ID;

IF RECORD_COUNT = 0 THEN
  /* Insert new record */
  EXEC SQL INSERT INTO CUSTOMERS ...;
ELSE
  /* Update existing record */
  EXEC SQL UPDATE CUSTOMERS ...;
END;


14.3.3 CICS Runtime Issues

"CICS Transaction not found"

Symptom:

CICS Error: Transaction 'CUST' not defined

Cause: Transaction not registered in CICS configuration.

Solution: Register transaction in cics-config.xml:

<cics-region>
  <transactions>
    <transaction id="CUST"
                 program="com.yourcompany.cics.CustomerInquiry"
                 description="Customer Inquiry"/>
  </transactions>
</cics-region>


"MAPFAIL condition raised"

Symptom:

CICS Condition: MAPFAIL
Unable to receive map data

Causes: - Map not sent before RECEIVE MAP - Incorrect map name - Map definition missing

Solutions:

/* Always send map before receive (pseudo-conversational) */

/* First transaction */
EXEC CICS SEND MAP('CUSTMAP');
EXEC CICS RETURN TRANSID('CUST');

/* Next transaction */
EXEC CICS RECEIVE MAP('CUSTMAP');  /* Now data is available */


14.3.4 Memory and Performance Issues

"OutOfMemoryError: Java heap space"

Symptom:

java.lang.OutOfMemoryError: Java heap space

Causes: - Large data structures - Array sizes too large - Memory leak in application

Solutions:

# Increase heap size
java -Xmx4G -jar myapp.jar

# For batch programs
export JAVA_OPTS="-Xmx8G -Xms2G"

# Monitor memory usage
jconsole <pid>

Optimize data structures:

/* Instead of large static arrays */
DCL CUSTOMERS(1000000) CUSTOMER_REC;  /* Too large! */

/* Use dynamic allocation or database queries */


"StackOverflowError"

Symptom:

java.lang.StackOverflowError

Causes: - Infinite recursion - Deeply nested %INCLUDE files - Very deep structure nesting

Solutions:

# Increase stack size
java -Xss4M -jar myapp.jar

# Fix recursion in code

Check for recursive calls:

/* Infinite recursion example */
PROC_A: PROCEDURE;
  CALL PROC_B;
END PROC_A;

PROC_B: PROCEDURE;
  CALL PROC_A;  /* ← Infinite loop! */
END PROC_B;


14.4 Manifold Issues

14.4.1 Compilation Issues

"OFFSET annotation is missing"

Symptom:

Warning: OFFSET annotation is missing on nested class 'Address'

Cause: Nested Group class not processed by Manifold.

Solutions: - Ensure class extends Group - Verify Manifold is in annotation processor path - Check file isn't excluded by filters

Gradle configuration:

dependencies {
    annotationProcessor 'com.heirloom:heirloom-manifold:2.0.0'
}

tasks.withType(JavaCompile) {
    options.compilerArgs += '-Xplugin:Manifold'
}


"Incorrect field offsets"

Symptom: Field offsets don't match expected PL/I layout.

Causes: - Wrong annotation values - Missing @Ignore on non-PLI fields - UNION handling issue

Solutions:

// Verify annotations match PL/I declarations
@CHAR(10) public String customerId;  // Must match DCL CUSTOMER_ID CHAR(10)
@DECIMAL(15, 2) public BigDecimal balance;  // Must match DEC FIXED(15,2)

// Use @Ignore for non-PLI fields
@Ignore
private transient String tempField;  // Won't be included in offsets

Debug offsets:

# Decompile class to verify $MetadataOffsets
javap -c -p MyGroup.class | grep -A20 '$MetadataOffsets'


"Generated methods not appearing"

Symptom: Getter/setter methods not generated by Manifold.

Causes: - Method already manually defined - Class doesn't extend Group - File excluded by filter

Solutions:

// Ensure class extends Group
public class CustomerRec extends Group {  // ← Must extend Group
    @CHAR(10) public String customerId;
}

// Remove manual getter/setter - let Manifold generate


14.4.2 Runtime Issues

"Cannot find $MetadataOffsets field"

Symptom:

NoSuchFieldError: $MetadataOffsets

Cause: Class compiled without Manifold processing.

Solutions: - Verify Manifold plugin active during compilation - Clean and rebuild: ./gradlew clean build - Check build logs for Manifold processing

Verify Manifold ran:

# Should show "Manifold: PropertyProcessor processing..."
./gradlew compileJava --info | grep Manifold


14.5 EBP Issues

14.5.1 Job Submission Issues

"JCL syntax error at line X"

Symptom:

JCL Error: Syntax error at line 15, column 20

Causes: - Invalid JCL syntax - Missing continuation - Column format error

Solutions:

/* Correct JCL format */
//STEPNAME EXEC PGM=com.yourcompany.MyProg,
//         PARM='PARAM1=VALUE1'

/* Continuation must be in column 72 or earlier */

Validate JCL:

# Submit with validation
curl -X POST http://localhost:8080/ebp/api/jobs?validate=true \
  -H "Content-Type: text/plain" \
  -d @myjob.jcl


"Program not found"

Symptom:

Job failed: Program 'com.yourcompany.MyProg' not found in classpath

Causes: - JAR not deployed to EBP - Wrong fully qualified class name - STEPLIB not configured

Solutions:

# Deploy JAR to EBP classpath
cp build/libs/myapp.jar /opt/ebp/lib/

# Restart EBP to reload classpath
systemctl restart ebp

# Verify class exists
jar -tf /opt/ebp/lib/myapp.jar | grep MyProg


"Dataset not found"

Symptom:

Job failed: Dataset 'MY.INPUT.FILE' not found

Causes: - Dataset doesn't exist - Wrong disposition (OLD on new file) - Incorrect dataset mapping

Solutions:

# Check dataset mapping
cat /opt/ebp/config/ebp.properties | grep data.root

# Create dataset directory
mkdir -p /var/ebp/data/MY/INPUT

# Create test file
echo "test data" > /var/ebp/data/MY/INPUT/FILE

Use correct disposition:

/* For existing file */
//INPUT DD DSN=MY.INPUT.FILE,DISP=SHR

/* For new file */
//OUTPUT DD DSN=MY.OUTPUT.FILE,DISP=(NEW,CATLG,DELETE)


14.5.2 Job Execution Issues

"Job stuck in QUEUED state"

Symptom: Job remains in QUEUED state indefinitely.

Causes: - Resource contention - Max concurrent jobs reached - Dataset lock

Solutions:

# Check EBP configuration
grep 'max.concurrent' /opt/ebp/config/ebp.properties

# Increase if needed
ebp.job.max.concurrent=10

# Check for dataset locks
curl http://localhost:8080/ebp/api/locks


"Job failed with RC=12"

Symptom:

Job completed with return code 12 (severe error)

Causes: - Program threw exception - SQL error - File I/O error

Solutions:

# View job output for error details
curl http://localhost:8080/ebp/api/jobs/JOB00123/output/SYSOUT

# Check for Java stack traces
curl http://localhost:8080/ebp/api/jobs/JOB00123/output/SYSPRINT

Common fixes: - Check SQL connection in program - Verify input file format - Review program logs


14.6 Debugging Techniques

14.6.1 Enable Debug Logging

Compiler debug:

java -jar pli_compiler2.jar \
  --source MYPROG.pli \
  --loglevel DEBUG  # ← Enable debug output

Runtime debug (logback.xml):

<configuration>
    <logger name="heirloom" level="DEBUG"/>
    <logger name="heirloom.sql" level="TRACE"/>
    <root level="INFO">
        <appender-ref ref="STDOUT"/>
    </root>
</configuration>


14.6.2 View Generated Code

View generated Java:

# Compiler output
cat generated/com/yourcompany/MYPROG.java

# Decompile .class file
javap -c build/classes/java/main/com/yourcompany/MYPROG.class


14.6.3 Inspect Metadata

View $MetadataOffsets:

// In code
Group myGroup = new MyGroup();
String[] offsets = MyGroup.$MetadataOffsets;
for (int i = 0; i < offsets.length; i += 2) {
    System.out.println(offsets[i] + " → " + offsets[i+1]);
}


14.6.4 Use Java Debugger

Debug with IntelliJ IDEA: 1. Import project as Gradle/Maven project 2. Set breakpoints in generated Java code 3. Run → Debug 'Main'

Debug with jdb (command-line):

# Compile with debug symbols
./gradlew build -Pdebug

# Run with debugger
jdb -classpath "build/libs/*" com.yourcompany.MYPROG


14.7 Getting Help

14.7.1 Support Resources

  • Documentation: https://support.heirloom.cc
  • Support Portal: Submit tickets for issues
  • Knowledge Base: Search for known issues and solutions

14.7.2 Information to Provide

When reporting issues, include:

  1. Platform versions

    # Compiler version
    java -jar pli_compiler2.jar --version
    
    # Runtime version
    grep 'version' pli_runtime2.jar/META-INF/MANIFEST.MF
    
    # Java version
    java -version
    

  2. Error messages (full stack trace)

  3. Minimal reproducible example

  4. Simplest PL/I code that shows the issue
  5. Build configuration (build.gradle or pom.xml)
  6. Commands used

  7. Environment details

  8. Operating system
  9. Application server (for CICS)
  10. Database (for SQL programs)