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:
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:
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:
"Type mismatch: expected TYPE1, found TYPE2"¶
Symptom:
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:
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:
"Circular include detected"¶
Symptom:
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:
"Invalid SQL syntax in EXEC SQL block"¶
Symptom:
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:
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:
Cause: Invalid JSON syntax in helper file.
Solution: Validate JSON:
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:
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:
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:
"ArrayIndexOutOfBoundsException"¶
Symptom:
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:
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:
"SQLCODE -803: Duplicate key error"¶
Symptom:
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:
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:
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:
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:
Causes: - Infinite recursion - Deeply nested %INCLUDE files - Very deep structure nesting
Solutions:
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:
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:
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:
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:
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:
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:
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:
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:
-
Platform versions
-
Error messages (full stack trace)
-
Minimal reproducible example
- Simplest PL/I code that shows the issue
- Build configuration (build.gradle or pom.xml)
-
Commands used
-
Environment details
- Operating system
- Application server (for CICS)
- Database (for SQL programs)