| bc-version |
domain |
keywords |
technologies |
countries |
application-area |
|
|
error-handling |
| insert |
| modify |
| delete |
| get |
| rename |
| boolean-return |
| clarify-before-building |
| ambiguous |
|
|
|
|
Ambiguous record-failure handling must be clarified, not guessed
Description
Insert, Modify, Delete, Get, and Rename all return a Boolean
indicating success. There are two legitimate ways to use that: let AL
raise its own runtime error when the return value is ignored and the call
fails, or check the return value explicitly and decide what happens on
failure (if not Rec.Insert() then ...). Both are correct in the right
context — an ignored Get() failing is often exactly the right behavior
when the record is expected to exist and its absence is a genuine bug;
an ignored Insert() failing on a duplicate key might instead be a normal,
recoverable case the caller should handle gracefully.
Because both are legitimate, this is not a pattern an AI assistant should
resolve by guessing. When it is unclear from the surrounding code, the
task description, or the object's existing conventions whether a given
failure should surface as AL's implicit runtime error or be handled
explicitly, ask the developer which behavior is intended before writing
the call — the same way clarify-before-building applies to any other
underspecified requirement. Silently picking one approach risks either
swallowing a failure the developer needed to see, or crashing a flow the
developer expected to degrade gracefully.
Best Practice
// Failure is expected and recoverable — handle it explicitly.
if not Customer.Insert() then
Error('Customer %1 already exists.', Customer."No.");
// Failure would indicate a genuine bug — let it surface as AL's own error.
Customer.Get(CustomerNo);
When genuinely unsure which case applies, ask: "Should a failed
Insert/Modify/Delete/Get here be handled as an expected, recoverable
outcome, or is it a bug we want to surface immediately?"
Anti Pattern
Silently choosing to ignore the return value (or silently choosing to wrap
every call in an if not ... then with a generic error message) without
first checking whether the surrounding code, task, or object convention
already signals which behavior is intended.