bcquality/microsoft/knowledge/breaking-changes/deprecate-public-members-with-the-obsolete-lifecycle.md
Jesper Schulz-Wedde 5706959e4a
Fix lifecycle compatibility guidance (#93)
* Fix lifecycle compatibility guidance

Correct high-confidence Business Central guidance and samples for upgrade tags, collectible errors, trigger semantics, obsoletion, events, interfaces, API contracts, and test transactions.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: e05a43e7-6448-4d67-9c73-798523f5d945

* Address guidance review findings

Gate SecretText guidance to BC23 and clarify that the collectible-error sample intentionally emits a message-only blocking aggregate.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: e05a43e7-6448-4d67-9c73-798523f5d945

---------

Co-authored-by: Jesper Schulz-Wedde <jesper.schulzwedde@microsoft.com>
2026-07-14 11:26:16 +02:00

2.1 KiB

bc-version domain keywords technologies countries application-area
all
breaking-changes
obsolete
deprecation
obsoletestate
obsoletetag
pending
removed
public-procedure
al
w1
all

Deprecate public members through the Obsolete lifecycle, never delete them outright

Description

Deleting or renaming a published procedure (or object) in a single release is a hard break: dependent extensions that reference it stop compiling the moment they pick up the new version, with no warning window to migrate. AL provides staged deprecation so consumers get advance notice. A procedure uses [Obsolete('reason', 'tag')]: it remains callable but callers receive a compiler warning naming the replacement and the version in which obsoletion began. Methods do not have ObsoleteState; after the deprecation window, the method is deleted, commonly through versioned preprocessor cleanup. Objects and fields instead use the ObsoleteState = Pending to Removed property progression.

Best Practice

When a published procedure is superseded, keep it in place and mark it [Obsolete('Use CalculateNetAmount instead.', '25.0')], where the message names the replacement and the tag records when the method became obsolete. Have the obsolete member forward to the new one so behavior is preserved during the window. Only after the deprecation window has elapsed should a later release delete the method. For an object or field, use Pending during the warning window and Removed afterward.

See sample: deprecate-public-members-with-the-obsolete-lifecycle.good.al.

Anti Pattern

Renaming or deleting the published CalcNet procedure in place — replacing it with CalculateNetAmount and nothing else — so consumers calling CalcNet break immediately with no deprecation notice. Detection: a previously shipped non-local procedure that vanished or was renamed between versions with no [Obsolete] marker left behind during a prior warning window. Do not suggest ObsoleteState = Removed for a method; that property belongs to supported object and element types.

See sample: deprecate-public-members-with-the-obsolete-lifecycle.bad.al.