Subfile Maintenance with Bob
In my last article, found here https://powerwire.uk/putting-ibm-i-bob-through-its-paces/, I asked Bob to create a subfile program used to maintain our database table called BookP and to be honest, it did a pretty good job! Nothing fancy but an efficient and well documented program.
A junior programmer could easily learn about subfiles in the source code. Just what was asked.
In this article, we will expand on this program and put some ‘meat on the bones’ as they say.
Starting Point
Firstly, let me show you the screen that Bob designed.

Yes, the More … should not be showing as we only have half a dozen records. Haven’t we all been there!
Error Handling
No RPG, or any other program, should scrimp and save on error handling. What does Bob suggest we do to improve error handling?
First thing to change was to put Bob in Plan mode, I do not want any changes made, I just want to know the error handling enhancements.
This is what it recommended.
BOOKM Error Handling Plan
Overview
BOOKM.SQLRPGLE has five distinct gaps. Only the RPG source needs to change,
BOOKM.DSPF is fine as-is. The four sub-tasks below are sequenced so each one builds cleanly on the last.

Sub-Task 1 — Richer SQL diagnostic helper SqlErrMsg
Intent: Every SQL failure message today only includes sqlcode. Adding sqlstate and sqlerrmc makes it possible to diagnose failures without checking a job log.
Expected outcomes:
- Two new module-level variables: hvSqlState char(5) and hvSqlErrmc char(70)
- A new SqlErrMsg procedure (prototype + implementation) that fetches sqlstate and sqlerrmc via GET DIAGNOSTICS and returns a formatted char(78) string
- All six existing SetMsg('... SQL ' + %char(sqlcode) + ').') calls in AddBook, ChangeBook, DeleteBook replaced with SetMsg(SqlErrMsg())
Relevant context:
Lines 239–244, 270–271, 307–312, 335–336, 357–360 of BOOKM.SQLRPGLE
Status: [ ] pending
Sub-Task 2 — Fix cursor re-declaration and guard OPEN/CLOSE
Intent:
DECLARE bookCsr lives inside LoadSubfile which is called every loop pass. Moving it to module scope removes the fragility. The OPEN and CLOSE are completely unchecked; a failure there silently shows an empty list with no message.
Expected outcomes:
- DECLARE bookCsr moved to module scope (above LoadSubfile)
- After OPEN: if sqlcode <> 0, call SetMsg(SqlErrMsg()) and return
- In the fetch loop: if sqlcode < 0 (real error, not just +100 EOF), call SetMsg(SqlErrMsg()) before leaving
- After CLOSE: if sqlcode <> 0, call SetMsg(SqlErrMsg())
Relevant context:
Lines 103–133 of BOOKM.SQLRPGLE. Requires Sub-Task 1.
Status: [ ] pending
Sub-Task 3 — Guard subfile update in ProcessOptions
Intent:
update BOOKSFL is called bare. A subfile I/O failure ends the program abnormally.
A monitor/on-error block catches it and surfaces a clean user message.
Expected outcomes:
- OPT = ' '; update BOOKSFL; wrapped in monitor / on-error
- On error: SetMsg called with a "Subfile update error" message, loop exits with leave
Relevant context:
Lines 192–193 of BOOKM.SQLRPGLE
Status: [ ] pending
Sub-Task 4 — Top-level monitor on the main loop
Intent:
Any unhandled RPG runtime exception (numeric conversion, array bounds, etc.) currently sends a raw escape message to the user. Wrapping the main dou loop in monitor/on-error guarantees a clean exit.
Expected outcomes:
- The entire dou indExit … enddo block wrapped in monitor/on-error
- on-error handler: calls SetMsg with a generic message, writes FOOTER to display it, sets *INLR = *ON, and returns
Relevant context:
Lines 72–93 of BOOKM.SQLRPGLE
Status: [ ] pending
Bob Coins
The enhancement itself was straightforward: I asked Bob to modernise and strengthen the program’s error handling.
The request consumed 3.09 Bob coins, which gives you a useful sense of scale, small refinements cost very little, while deeper structural changes require more investment.
For context, 3.09 Bob coins equates to roughly £0.31 GBP, €0.36 EUR or $0.38 USD.
It’s a tiny amount, but that’s precisely the point: Bob’s coin system gives developers a clear, predictable indicator of how “heavy” an AI‑generated change is.
You can see, at a glance, whether you’re asking Bob for a minor tidy‑up or a more substantial refactor.
Conclusion
Bob didn’t just generate code, it behaved like a junior developer who understands IBM i conventions and can justify its recommendations.
The error‑handling plan shows exactly where the weak spots are, why they matter and how to fix them without turning the program upside down.
That’s the real value: Bob gives you structured, incremental improvements that make legacy RPG code safer, clearer and easier to maintain. As we continue exploring Bob’s capabilities, it’s becoming clear that AI on IBM i isn’t about replacing developers, it’s about accelerating the parts of the job that used to be slow, manual or overlooked. If strengthening a production‑ready program costs just over three Bob coins, the cost‑to‑benefit ratio speaks for itself.
GitHub
If you want to check out exactly what Bob did with this code, I have placed the RPG and display file, in PowerWire’s GitHub repository, found here https://github.com/PowerWire-Code/Bob