Blog › ICP guides
RPGLE developer on retainer: EVAL-CORR field mismatch, free-format RPG, ILE RPG, IBM i RPGLE on monthly retainer
October 8, 2026 · ~16 min read
An ILE RPGLE developer was maintaining an order processing application in free-format RPG on IBM i (V7R4). The application included a batch order loading program (ORDER.LOAD) that read inbound order data from a staging file, populated an in-memory data structure, and wrote new records to the order header file (ORDHDR). The program used an externally-described data structure for the order header — DCL-DS ds_order EXTNAME('ORDHDR') END-DS — which automatically reflected the field names and types defined in ORDHDR’s DDS source. It also used a separately-defined qualified input data structure — DCL-DS ds_input QUALIFIED END-DS — that replicated the layout of the staging file. To copy fields from ds_input into ds_order before writing, the developer used the free-format EVAL-CORR opcode: EVAL-CORR ds_order = ds_input. A database administrator performed a schema migration that renamed the ORDHDR field order_custid to order_customer_id to align with a new corporate naming standard. The DBA regenerated the ORDHDR DDS source, recompiled ORDHDR, and the externally-described ds_order data structure in ORDER.LOAD automatically reflected the new field name after recompilation. But ds_input still contained the old field name order_custid. ORDER.LOAD recompiled without error. No RPG compiler warning was issued. The batch job ran without error. Four orders were written to ORDHDR with blank customer IDs.
The root cause was EVAL-CORR’s matching semantics. In free-format ILE RPGLE, EVAL-CORR (EVALuate CORRespondingly) copies field values from one data structure to another by matching fields with the same name AND compatible type. For each field in the target data structure (ds_order), EVAL-CORR looks for a field in the source data structure (ds_input) with the same name. If it finds a matching field with a compatible type, it copies the value. If it does not find a matching name in the source — as happened with order_customer_id in ds_order after the schema rename, because ds_input still had order_custid — the corresponding target field retains its initialization value: blanks for character fields, zero for numeric fields. EVAL-CORR does not issue a runtime error, a runtime warning, or any indication that one or more target fields received no value from the source. The RPG compiler also does not warn about EVAL-CORR pairs where some target fields have no corresponding source field — the assumption is that the programmer intentionally left those fields at their default values. The fix was to rename order_custid to order_customer_id in ds_input to match the updated schema field name, so EVAL-CORR could again find the matching pair and copy the customer ID correctly. Orders written with blank customer IDs: 4 → 0.
EVAL-CORR is one of the most powerful and most dangerous opcodes in the ILE RPGLE free-format repertoire. Its power is its convenience: copying 30 fields between two data structures with a single EVAL-CORR statement, rather than 30 explicit field-by-field assignments, eliminates repetitive code and reduces maintenance burden when fields are added to both structures simultaneously. Its danger is the same property that makes it convenient: the silent default behavior when names don’t match. In a typical ILE RPGLE application, externally-described data structures (EXTNAME) are regenerated automatically when their underlying database file is recompiled after a DDS schema change. User-defined data structures (not EXTNAME) are not automatically updated — they must be manually aligned to match any schema changes. Any EVAL-CORR between an EXTNAME data structure and a user-defined data structure is at risk when the schema changes: the EXTNAME structure updates automatically, the user-defined structure does not, and EVAL-CORR silently stops copying the renamed field. The developer must audit all EVAL-CORR pairs after any schema rename to verify that both sides still have matching names for every critical field. A post-rename regression test that verifies each output field has a non-default value would have caught this before production.
ILE RPGLE free-format programs also use the LIKE keyword in DCL-DS definitions as an alternative to EXTNAME: DCL-S order_cust_id LIKE(ORDHDR.order_custid) defines a standalone field with the same length and type as the ORDHDR field by name. After the ORDHDR schema rename, DCL-S order_cust_id LIKE(ORDHDR.order_custid) would produce a compiler error (unknown field name) — catching the rename at compile time. But DCL-DS ds_input QUALIFIED END-DS with manually-specified field names (not LIKE references) does not check against the schema at compile time; it only fails silently at runtime via EVAL-CORR mismatches. The safest pattern for ILE RPGLE programs that read from and write to the same file is to use a single EXTNAME data structure for both source and target — eliminating the EVAL-CORR pair entirely and working directly with the externally-described fields. Where a separate staging-file data structure is genuinely needed, using LIKE references for all critical field types (rather than manually typing lengths and decimal positions) reduces the risk of type-mismatch failures after schema changes, and writing explicit field-by-field assignments instead of EVAL-CORR ensures that any schema rename is immediately flagged at compile time.
ILE RPGLE, free-format RPG, and the EXTNAME data structure model
RPG — Report Program Generator — was originally developed by IBM for the IBM 1401 in 1959. It was designed for business data processing: reading records from punched cards or sequential files, applying calculations, and printing formatted reports in a column-oriented fixed-format source coding style that matched the column-by-column layout of punched card programming forms. RPG II arrived on the System/3 and System/34 through the late 1960s and 1970s, adding the RPG program cycle (the implicit read-process-write loop that drove most RPG programs without requiring explicit I/O operations) and externally-described files that read field definitions directly from the database file’s DDS source. RPG III followed on the System/38 in 1979, introducing structured programming constructs (IF/ELSE/ENDIF, DO/ENDDO, subroutines with EXSR/BEGSR/ENDSR) and a richer I/O model. RPG/400 on the AS/400 (launched in 1988) extended RPG III with multi-occurrence data structures and enhanced string handling. ILE RPG (RPG IV) was introduced with OS/400 V3R2 in 1994, bringing a fully procedural syntax, procedure pointers, service programs, a binding model inherited from ILE (Integrated Language Environment), and a new source format that broke from the strict 80-column card-image layout that had defined RPG since 1959.
Free-format ILE RPGLE was introduced in RPG IV with V5R1 (2001), allowing free-form syntax within /FREE and /END-FREE delimiter blocks. Within those blocks, opcodes, operands, and expressions no longer required specific column positions: IF, DOW, DOU, FOR, SELECT/WHEN/OTHER/ENDSL, CHAIN, READ, WRITE, UPDATE, and EVAL could be written in any column with free-form spacing. The rest of the program — H-spec (header), F-spec (file), D-spec (definition), and P-spec (procedure) lines — remained fixed-format. Fully-free format, which eliminated the /FREE / /END-FREE requirement and allowed free-form syntax for all specification types including header, file, and definition specs (now written as CTL-OPT, DCL-F, and DCL-DS / DCL-S / DCL-PR / DCL-PI), was introduced in IBM i 7.1 TR7 (2013) and formalized as the standard coding style in V7R2 (2014). Fully-free format is the current recommended style for new ILE RPGLE development; fixed-format programs continue to compile and run on IBM i V7R1 through V7R5 without modification.
The externally-described file model is central to ILE RPGLE. DCL-F ORDHDR DISK KEYED declares the ORDHDR physical file as a program-described keyed file; DCL-F ORDHDR DISK KEYED USAGE(*INPUT : *OUTPUT : *UPDATE) declares both read and write access. For externally-described files, all I/O operations use field names defined in the file’s DDS source directly as program variables — no separate data structure declaration is required. DCL-DS ds_order EXTNAME('ORDHDR') END-DS declares an externally-described data structure that mirrors the ORDHDR layout: subfield names and types are generated at compile time by reading the DDS field definitions for ORDHDR. After compilation, the program object contains subfield layouts that match the DDS source at the time of compilation. If the DDS source is changed and ORDHDR is recompiled, any RPGLE program using EXTNAME('ORDHDR') must also be recompiled for its subfield layout to reflect the updated schema — a stale program object compiled against old DDS will have a mismatch between its embedded field layout and the physical file’s current layout, which produces a level-check error at runtime (MCH3601 or CPF4131 depending on the access method).
EVAL-CORR semantics in detail: EVAL-CORR target-ds = source-ds iterates over every subfield defined in target-ds. For each target subfield, it searches source-ds for a subfield with the same name (case-insensitively — Order_CustID matches ORDER_CUSTID) and a compatible type (character to character, numeric to numeric with automatic decimal scaling). If a match is found, the source value is assigned to the target subfield. If no match is found — because the names differ, as happened with order_custid (in ds_input) vs order_customer_id (in ds_order after the schema rename) — the target subfield retains its current value. For a freshly initialized data structure, that current value is the initialization value: *BLANKS for character fields, *ZEROS for numeric fields, *LOVAL for date fields initialized to low value. EVAL-CORR produces no RPG compiler message (not even an informational) for unmatched target fields. The RPG IV compiler cannot warn about EVAL-CORR pairs with missing source matches because matching is resolved at runtime against the data structures’ runtime subfield names — although in practice, for programs that use EXTNAME-sourced data structures compiled from DDS, the subfield names are entirely determined at compile time and a dedicated compiler analysis pass could theoretically detect the mismatch. IBM has not added such a warning as of IBM i V7R5.
The %FOUND built-in function in ILE RPGLE reflects the result of the most recent file operation for a named file: %FOUND(INVMAST) is *ON if the last CHAIN, READ, READE, READPE, SETLL, SETGT, or DELETE on INVMAST found a matching record, and *OFF if it did not. Unlike the RPG IV indicator approach (which stores the found/not-found state in a specific indicator number like *IN50 that is global to the entire program), %FOUND(file-name) is specific to the named file but still reflects only the most recent operation on that file at the time it is evaluated. A subprocedure that issues a CHAIN to any file (even a different file, if that same file name was operated on) will overwrite the %FOUND state for that file. The safest pattern is to capture %FOUND(INVMAST) into a local indicator variable immediately after the CHAIN INVMAST operation: inv_found = %FOUND(INVMAST), then check inv_found rather than %FOUND(INVMAST) after any intervening subprocedure calls.
The ILE binding model underlies all ILE RPGLE programs. An RPGLE source file is compiled into an ILE module (CRTRPGMOD). One or more ILE modules are bound together into an ILE program (CRTPGM) or an ILE service program (CRTSRVPGM). Service programs expose exported procedures that other programs or service programs can call; the exported procedure names are controlled by a binding source (BNDDIR) or module export list. Activation groups control how static storage (module-level variables declared with STATIC storage class) and open file handles are managed: *CALLER means the service program runs in the caller’s activation group, sharing its static storage across calls (static variables retain their values between calls, open file cursors remain open); *NEW creates a new activation group for each activation, reinitializing all static storage and closing all open file handles when the activation ends (typically when the program that called the service program ends); a named activation group (e.g., ACTGRP('ORDPROC')) allows multiple programs to share the same persistent activation group and its static storage. Choosing the wrong activation group can cause unexpected static variable retention across program calls (*CALLER when *NEW was intended) or unexpected static variable reinitialization (the reverse).
SQLRPGLE embeds SQL in free-format RPG using EXEC SQL ... END-EXEC blocks. The SQL precompiler translates EXEC SQL blocks to RPG opcodes before the RPG compiler processes the source. Host variables are RPG variables prefixed with a colon in SQL: EXEC SQL SELECT unit_price INTO :hv_unit_price FROM ORDER_LINE WHERE line_id = :hv_line_id selects the unit_price column into the RPG host variable hv_unit_price. For nullable columns, SQL requires a companion null indicator variable: EXEC SQL FETCH cursor1 INTO :hv_unit_price :nullind_unit_price — if unit_price is NULL in the fetched row, the SQL runtime sets nullind_unit_price to a negative value (typically -1) and leaves hv_unit_price unchanged (retaining its initialization value, usually 0 for a numeric). If the application checks hv_unit_price without first checking whether nullind_unit_price < 0, it silently uses 0 as the price for NULL-priced items. SQLCOD (SQLCODE) and SQLSTATE are host variables that reflect the completion status of the most recent SQL statement: SQLCOD = 0 means successful completion; SQLCOD = 100 means no rows found (equivalent to SQLSTATE = '02000'); negative SQLCOD values indicate errors. IBM i V7R1 through V7R5 introduced progressive SQL feature additions: V7R1 added temporal tables; V7R2 added row change timestamps and named parameters in SQL procedures; V7R3 added in-memory temporary result sets; V7R4 and V7R5 added JSON functions and further SQL optimizer improvements.
Typical RPGLE retainer work and what it looks like in a work log
EVAL-CORR field mismatch after schema rename is the canonical free-format RPGLE silent data loss pattern and the most systematically underlogged category of RPGLE retainer work. The mechanics are consistent: a DBA renames a field in DDS (or SQL DDL) to align with a new naming convention; regenerates the DDS source; recompiles the physical file; the RPGLE program’s EXTNAME data structure auto-updates after recompilation; the manually-typed user-defined input data structure does not update; EVAL-CORR silently stops copying the renamed field and assigns the initialization value instead. The program compiles clean. The program runs to completion without error. The first indication of a problem is downstream: an order with a blank customer ID fails an order fulfillment validation check, a report shows zero-dollar totals for records that should have amounts, or a billing run produces invoices with no customer reference. By the time the symptom surfaces, multiple records may have been written with the silent default value. Work log entry: “ORDER.LOAD: EVAL-CORR ds_order = ds_input; ORDHDR field renamed order_custid → order_customer_id; ds_input field name not updated; 4 orders written with blank order_customer_id; ds_input field renamed to match schema; blank customer IDs: 4 → 0; 1.5h.”
%FOUND stale result after subprocedure call is the second most common RPGLE retainer pattern in free-format programs, and it is distinct from the RPG IV indicator overwrite pattern covered in the RPG IV developer retainer post (which describes the classic global *IN50 indicator hazard in fixed-format RPG). In free-format ILE RPGLE, %FOUND(file-name) is specific to the named file, but it still reflects only the most recent operation on that file. The failure scenario: a developer issued CHAIN key INVMAST to look up an inventory master record, then called the CalcReorderPt subprocedure to compute a reorder threshold based on that record’s data. CalcReorderPt internally issued its own CHAIN to VENDATA (a vendor data file) that did not find a matching record, setting %FOUND(*OFF) for the most recent file operation. When control returned to the calling procedure, the IF %FOUND(INVMAST) check evaluated based on CalcReorderPt’s VENDATA chain result — not the original INVMAST chain — and four INVMAST records that had been found correctly were skipped without being updated. Fix: capture inv_found = %FOUND(INVMAST) immediately after the CHAIN key INVMAST operation, before calling CalcReorderPt, and use IF inv_found for the subsequent check. Work log entry: “INVMAST update loop: %FOUND(INVMAST) checked after CalcReorderPt call; CalcReorderPt issued CHAIN VENDATA (not found, set %FOUND *OFF); IF %FOUND(INVMAST) returned *OFF; 4 INVMAST records not updated; captured inv_found = %FOUND(INVMAST) before CalcReorderPt call; skipped records: 4 → 0; 2h.”
SQLRPGLE null indicator not checked is the third common RPGLE retainer pattern in shops that have modernized from pure DDS-based RPGLE to SQLRPGLE with embedded SQL. The null indicator variable is declared alongside each host variable for nullable columns, but it is frequently never checked — either because the developer did not know the column was nullable, because the column became nullable after a schema change that added NULL as a permitted value, or because the null indicator was declared but treated as a formality. The failure scenario: an order report program used EXEC SQL FETCH cursor1 INTO :hv_unit_price :nullind_unit_price to retrieve order line data; three ORDER_LINE rows with NULL in the unit_price column populated hv_unit_price with 0 (the RPG initialization value for packed numeric, since the SQL runtime leaves the host variable unchanged when the column is NULL); the subtotal calculation multiplied hv_unit_price by quantity, producing zero-dollar subtotals for those three lines; the invoices were generated with line items showing $0.00. No SQL error occurred — SQLCOD was 0 for each successful fetch, including the fetches for NULL-priced rows. Fix: add IF (nullind_unit_price < 0) to detect the null indicator and handle the NULL case explicitly (log an error, use a default price, or skip the line) before using hv_unit_price in calculations. Work log entry: “ORDRPT: EXEC SQL FETCH cursor1 INTO :hv_unit_price :nullind_unit_price; nullind_unit_price never checked; 3 ORDER_LINE rows with NULL unit_price fetched as 0; zero subtotals in 3 invoice lines; null indicator check added; wrong lines: 3 → 0; 1.5h.”
Track RPGLE developer retainer hours without the status emails
When a 1.5-hour investigation traces 4 orders written with blank customer IDs to a schema rename that broke an EVAL-CORR pairing between an auto-updated externally-described data structure and a manually-typed input data structure — EVAL-CORR silently assigns the initialization value (blanks) to any target field with no matching source name — the work log must name the program, the EVAL-CORR pair, the renamed field, the initialization value used (blanks), and the order count before and after the fix. HourTab gives your RPGLE retainer client a public dashboard URL they can bookmark: hours used, hours remaining, and a work log naming the EVAL-CORR field mismatch and the fix. No client login. No status emails. CSV in, URL out.
See HourTab pricing →How HourTab tracks RPGLE retainer hours
EVAL-CORR mismatches are invisible by the same mechanism that makes them dangerous. In development, the developer verifies that the EVAL-CORR statement compiles without error — the RPG compiler issues no warning for EVAL-CORR pairs with unmatched field names; it issues no informational message; the compilation job log shows zero diagnostic messages related to the unmatched pair. The program runs through a test cycle without error. In a test environment with a handful of sample records where the staging file happens not to contain any records that expose the omitted field, the silent blank assignment may produce records that pass initial validation checks (an empty customer ID string might pass a “not-null” check in RPG if the check only tests %LEN(%TRIM(ds_order.order_customer_id)) > 0 after the field was a fixed-length character field initialized to blanks — the field is blank, not null, and the trim-length check returns 0, which the developer did not anticipate as a test case). Only downstream processing that requires a valid customer ID — a billing run that looks up the customer account, an order fulfillment system that routes based on customer ID, a report that groups by customer — discovers the missing value. By that point, production records with blank customer IDs have already been written and must be corrected manually.
The work log needs to name the mechanism precisely: the program name (ORDER.LOAD), the EVAL-CORR pair (EVAL-CORR ds_order = ds_input), which data structure was EXTNAME-sourced and auto-updated (ds_order via EXTNAME('ORDHDR')), which was manually-typed and not updated (ds_input), the field whose name changed (order_custid in ds_input not updated to match order_customer_id in ds_order after the ORDHDR DDS rename), the initialization value silently assigned to the unmatched target field (blanks — character field), the records affected and the count before and after fix (4 orders with blank order_customer_id before the fix; 0 after), and hours (1.5h). A log entry that says “fixed order loading bug, 1.5h” is not auditable by the client, is not defensible against a future dispute about whether the fix was correctly scoped, and does not help the next developer who inherits the codebase understand where EVAL-CORR pairs exist that require ongoing alignment discipline after schema changes. A log entry that names the EVAL-CORR pair, the renamed field, and the EXTNAME vs manually-typed data structure distinction is auditable, defensible, and useful as institutional documentation. HourTab gives RPGLE developers a public retainer-hours URL they send to clients — IBM i and AS/400 shops running ILE RPGLE batch programs, interactive programs, and service programs in financial services, distribution, manufacturing, and healthcare, where the IBM i installed base is large and the developer pool is small and aging.
Comparative context for adjacent silent-failure patterns in enterprise batch environments: RPG IV developer retainers cover the classic RPG IV global indicator overwrite hazard — where a called program or subroutine that uses the same indicator number (e.g., *IN50) as the caller for its own file operations overwrites the caller’s indicator state, causing the wrong branch to execute on return. EVAL-CORR and the free-format %FOUND(file-name) pattern partially address the indicator hazard by moving away from global program indicators, but introduce the EVAL-CORR name-matching silent failure class instead. SAS PROC SORT NODUPKEY developer retainers cover a structurally similar pattern from a different enterprise batch ecosystem: a SAS operation (PROC SORT NODUPKEY) that succeeds without error but silently removes valid records from the output dataset when duplicate key values appear, producing a downstream dataset that has fewer observations than the source without any warning in the SAS log. Both the RPGLE EVAL-CORR mismatch and the SAS NODUPKEY pattern share the same fundamental property: the operation completes successfully, the job log shows no errors, and the data loss is only discoverable by an independent validation step that checks the output record count or field values against an expected reference. Progress OpenEdge developer retainers cover the implicit transaction model in Progress 4GL, where a batch ABL program that does not explicitly define transaction boundaries may commit partial updates under certain error conditions — another IBM i and legacy enterprise batch invisible-bug class where the program produces a partially-correct result without any runtime error indication.
FAQ: RPGLE developer retainers
What does an RPGLE developer on retainer typically do?
An RPGLE developer on monthly retainer covers EVAL-CORR field-name alignment audits after schema changes (reviewing all EVAL-CORR pairs in the application to verify that both the EXTNAME externally-described data structure and any manually-typed user-defined data structures share the same field names, catching any rename that the EXTNAME structure picked up automatically but the user-defined structure did not); %FOUND capture discipline reviews (confirming that %FOUND(file-name) results are captured into local indicator variables immediately after the file operation rather than checked later after an intervening subprocedure call that may issue its own file operation, overwriting %FOUND); SQLRPGLE null indicator reviews (verifying that host variable declarations include null indicator companion variables and that every EXEC SQL FETCH block checks the null indicator before using the host variable value); ILE binding model and activation group reviews (*CALLER vs *NEW vs named activation groups — confirming that static storage and open file handle behavior across activation groups matches the design intent); and EXTNAME data structure recompile planning after DDS or SQL DDL schema changes (identifying all programs and service programs that use a changed file’s EXTNAME and scheduling a recompile sequence that rebuilds all dependent objects in dependency order).
What RPGLE EVAL-CORR work is most commonly underlogged?
EVAL-CORR field-name mismatches after schema renames are the most systematically underlogged RPGLE retainer work. The pattern: a DBA renames a field in DDS (or SQL DDL) to align with a new naming standard; recompiles the physical file; the RPGLE program’s EXTNAME data structure (DCL-DS ds_target EXTNAME('FILENAME') END-DS) automatically reflects the new field name after the program is recompiled; the manually-typed input data structure (DCL-DS ds_input QUALIFIED END-DS with manually specified subfield names) still contains the old field name because it was not updated to match; EVAL-CORR ds_target = ds_input copies all matching fields by name and silently assigns the initialization value (blanks for character fields, zero for numeric) to any target field whose name no longer matches a source field. The program compiles clean. The program runs without error. No RPG compiler warning is issued for EVAL-CORR pairs where some target fields have no corresponding source field. Only downstream processing that relies on the previously-copied field notices the missing value — often in production, after records have already been written with default (blank or zero) values in the critical field.
What are typical RPGLE developer retainer rates?
Entry-level ILE RPGLE developers with experience in basic free-format RPG programming, externally-described files, DCL-DS data structure definitions, and standard batch program development typically bill at $80 to $145 per hour. Mid-level RPGLE programmers with experience in EVAL-CORR pair management, SQLRPGLE embedded SQL, ILE binding model (modules, service programs, binding directories), and %BIF built-in function repertoire typically bill at $120 to $210 per hour. Senior RPGLE developers with deep knowledge of IBM i V7R1 through V7R5 compatibility, activation group architecture (*CALLER vs *NEW vs named), DDS and SQL DDL schema change impact analysis, and complex ILE service program design typically bill at $165 to $305 per hour. Monthly retainer ranges: $2,000 to $3,600 per month for advisory engagements covering EVAL-CORR audits, schema change impact assessment, and architecture reviews (14 to 22 hours per month); $2,800 to $5,600 per month for active maintenance. Premium rates reflect the market reality: IBM i and AS/400 RPGLE expertise is rare and highly compensated, as the IBM i installed base is served by a shrinking pool of experienced developers.
What should an RPGLE developer retainer agreement include?
An RPGLE developer retainer agreement should specify: IBM i OS version (V7R1 through V7R5 — each release introduced new free-format opcodes, SQL enhancements, and compiler options; the retainer scope should identify the production release and any PTF levels that affect supported syntax); free-format RPG vs fixed-format (fully-free format requires IBM i 7.1 TR7 or V7R2 and later; some legacy programs still use fixed-format or mixed /FREE … /END-FREE blocks and have different opcode constraints); EXTNAME vs SQL DDL schema definitions (DDS-defined files use EXTNAME with the physical file name; SQL DDL-defined tables require EXTNAME with the schema-qualified table name or a file override; the retainer scope should clarify which schema management approach the application uses and who owns schema changes); SQLRPGLE scope (whether the retainer includes embedded SQL programs and SQLRPGLE-specific work: cursor management, null indicator discipline, SQLCOD and SQLSTATE checking, SQL precompiler options); ILE binding directory and service program inventory (identifying all service programs the application depends on, their activation group settings, and which modules must be recompiled and re-bound after source changes); and recompile sequencing responsibility (who schedules and executes the CRTRPGMOD / CRTPGM / CRTSRVPGM recompile sequence after schema changes, and who validates that all dependent programs are updated before the maintenance window closes).
How should RPGLE developer retainer hours be logged?
Log each RPGLE retainer session with the specific program, opcode or construct, and field-level specifics. For EVAL-CORR field-name mismatch bugs: program name (ORDER.LOAD), EVAL-CORR pair (EVAL-CORR ds_order = ds_input), the field whose name changed (order_custid renamed to order_customer_id in ORDHDR DDS), which data structure auto-updated (ds_order via EXTNAME) vs which did not (ds_input — manually typed, not EXTNAME), the initialization value silently assigned (blanks — character field), the records affected and count before and after fix (4 orders with blank order_customer_id before; 0 after renaming ds_input field to match), hours (1.5h). For %FOUND stale result bugs: program name, file operation (CHAIN INVMAST), the intervening subprocedure call that overwrote %FOUND, the file that subprocedure operated on, the records not processed as a result, the fix (capture %FOUND into local indicator before subprocedure call), hours. For SQLRPGLE null indicator bugs: program name, EXEC SQL operation (FETCH cursor1 INTO :hv_unit_price :nullind_unit_price), the nullable column (unit_price), the default value used when null indicator was not checked (0), records affected, fix (null indicator check added), hours.