Lease Modification and Remeasurement Accounting Under ASC 842 and IFRS 16
How to account for lease modifications and remeasurements under ASC 842 and IFRS 16 — separate lease vs remeasurement, which discount rate applies, ROU vs P&L offsets, and runnable Python.
A lease almost never runs untouched from commencement to expiry. Rents are renegotiated, floors are handed back, renewal options flip from unlikely to reasonably certain, and CPI clauses reset. Each of those events forces a decision that most lease engines get subtly wrong: is this a brand-new lease, a remeasurement of the existing liability at a revised rate, or a reassessment that keeps the original rate — and does the offsetting entry land on the right-of-use asset or in profit or loss? Choosing the wrong branch does not throw an exception; it silently misstates the liability, the asset, and every interest accrual for the remaining term. This page is the decision layer that sits on top of the ASC 842 and IFRS 16 core architecture and right-of-use models: it specifies, for accountants and engineers alike, exactly which rate to discount at, which carrying amount absorbs the difference, and how to encode that branching in deterministic, Decimal-precise Python. It covers two focused how-tos in depth — accounting for a lease modification in Python and the partial lease termination remeasurement mechanics — and it ties every branch back to a recomputed present value and a fresh discount rate.
Standard References: Modification, Remeasurement, and Reassessment Link to this section
The two frameworks converge almost completely here, which is fortunate for a single codebase. The vocabulary matters, because the standards attach different mechanics to three words that practitioners often blur.
-
Separate lease (a modification that grants additional right of use). Under IFRS 16.44 and ASC 842-10-25-8, a modification is accounted for as a separate lease when both conditions hold: it increases the scope of the lease by adding the right to use one or more underlying assets, and the consideration increases by an amount commensurate with the standalone price for that additional right of use (adjusted for the circumstances of the contract). When both are met, the original lease is untouched and the addition is a new lease with its own commencement-date measurement and its own rate.
-
Modification that is not a separate lease. Any other change in scope or consideration is a remeasurement. IFRS 16.45 requires the lessee, at the effective date, to remeasure the lease liability by discounting the revised lease payments at a revised discount rate. The offset then splits on direction: for a decrease in scope the lessee reduces the carrying amount of the right-of-use asset to reflect the partial or full termination and books any resulting gain or loss to profit or loss (IFRS 16.46(a)); for all other modifications the lessee makes a corresponding adjustment to the right-of-use asset (IFRS 16.45(b)). ASC 842-10-25-9 through 25-18 prescribe the same treatment, with ASC 842-10-25-11 covering the remeasurement and reallocation and ASC 842-10-25-13 covering the proportionate reduction for a decrease in scope, plus a mandatory reassessment of lease classification at the modification date.
-
Reassessment without a modification. A reassessment re-evaluates an estimate under the existing contract terms — no renegotiation occurred. The rate rule bifurcates. A change in the assessment of the lease term or of a purchase option (becoming, or ceasing to be, reasonably certain) is remeasured at a revised discount rate under IFRS 16.40 and ASC 842-20-35-4/5. A change in future payments driven by an index or rate (a CPI reset, a market-rent review) is remeasured using the original, unchanged discount rate under IFRS 16.42–43 — the exception being a change in floating interest rates, which does move to a revised rate. In every reassessment case the offset adjusts the right-of-use asset (IFRS 16.39), and only a reduction that would drive the asset below zero spills into profit or loss.
The controls consequence is that a modification or reassessment is not an ad-hoc journal — it is a re-run of the commencement-date measurement engine with a precisely chosen rate and a precisely chosen offset target. Whether a given change is even material enough to trigger a full remeasurement rather than a prospective adjustment is governed by threshold tuning for materiality, and every remeasured liability then re-enters the lease liability rollforward and reconciliation as a non-cash movement.
Input / Output Specification: Event Type, Rate, and Offset Target Link to this section
Pin the contract before writing any arithmetic. The single most valuable artifact on this page is the mapping from event type to the rate to discount at and the account the offset lands in — get this table into code as an explicit branch and most modification defects disappear.
| Event type | Separate lease? | Rate to use | Offset target |
|---|---|---|---|
| Additional right of use at standalone price | Yes | New rate for the new lease | New ROU asset and new liability; original untouched |
| Modification increasing payments or extending term | No | Revised rate at effective date | Adjust the ROU asset by the change in liability |
| Modification decreasing scope (partial termination) | No | Revised rate at effective date | Reduce ROU proportionately; gain or loss to P&L |
| Reassessment of lease term or purchase option | No | Revised rate | Adjust the ROU asset |
| Reassessment for an index or rate change (CPI) | No | Original locked rate | Adjust the ROU asset |
| Reassessment for a floating interest-rate change | No | Revised rate | Adjust the ROU asset |
| Change in residual value guarantee expected to be owed | No | Original locked rate | Adjust the ROU asset |
Two rules carry most of the weight. First, only two families use the revised rate — separate-lease additions (their own new rate), modifications, and term or purchase-option or floating-rate reassessments; index-and-rate resets and residual-value-guarantee changes keep the original locked rate. Second, only one branch ever touches profit or loss on the measurement itself: a decrease in scope. Every other event routes the whole difference through the right-of-use asset. Encoding those two rules as a lookup, rather than as scattered if statements, is what keeps a portfolio engine auditable.
Formula Block: Revised Liability, ROU Adjustment, and Proportional Reduction Link to this section
Every branch reuses one primitive — the present value of the revised remaining payments — and differs only in the rate fed to it and where the difference is posted. Let
where
where
For a decrease in scope, the mechanics are two-stage. Let
a positive result being a gain (more liability released than asset written off). Then re-discount the retained payments at the revised rate; any residual difference adjusts the retained asset:
where
Step-by-Step Python Implementation Link to this section
The following module implements the whole decision table as one branch. It uses decimal.Decimal for exact money, an Enum to make the event type explicit, and a single revised_liability primitive that every branch reuses. The offset routing — right-of-use asset versus profit or loss — is decided entirely by the event type, never inferred from the sign of a number.
Step 1 — Precision, rounding, and the shared present-value primitive. Pin the context precision, define a cent quantizer, and write the one function that discounts the revised remaining payments. Every branch calls it; only the rate passed in changes.
from dataclasses import dataclass
from decimal import Decimal, ROUND_HALF_UP, getcontext
from enum import Enum
getcontext().prec = 28 # audit-grade; no float drift in the PV sum
CENT = Decimal("0.01")
def q(x: Decimal) -> Decimal:
"""Round to the cent, half-up — the convention auditors re-derive."""
return x.quantize(CENT, rounding=ROUND_HALF_UP)
def revised_liability(payments: tuple[Decimal, ...], rate: Decimal) -> Decimal:
"""PV of revised remaining payments (ASC 842-20-30-1 / IFRS 16.26)."""
return sum(
(p / (Decimal(1) + rate) ** k for k, p in enumerate(payments, start=1)),
Decimal("0"),
)
Step 2 — Classify the event and select the rate. The Event enum encodes the rows of the specification table. applicable_rate is the compliance rule made executable: index-and-rate resets and residual-value-guarantee changes keep the original rate; everything else uses the revised rate (IFRS 16.42–43 vs IFRS 16.40/45).
class Event(Enum):
SEPARATE_LEASE = "separate_lease" # IFRS 16.44 / ASC 842-10-25-8
MODIFICATION = "modification" # payments/term change, not a scope decrease
SCOPE_DECREASE = "scope_decrease" # partial termination, IFRS 16.46(a)
REASSESS_TERM = "reassess_term" # term / purchase option, revised rate
REASSESS_INDEX = "reassess_index" # CPI or RVG change, original rate
def applicable_rate(event: Event, original_rate: Decimal, revised_rate: Decimal) -> Decimal:
"""Original rate for index/rate & RVG reassessments; revised rate otherwise."""
return original_rate if event is Event.REASSESS_INDEX else revised_rate
Step 3 — Remeasure, and route the offset by event type. For a decrease in scope the code derecognizes the given-up proportion first and books the difference to profit or loss (IFRS 16.46(a) / ASC 842-10-25-13), then re-discounts the retained payments. For every other event the change in liability adjusts the right-of-use asset, with a floor-at-zero spill to P&L (IFRS 16.39).
@dataclass(frozen=True)
class Position:
rou: Decimal # right-of-use asset carrying amount
liability: Decimal # lease liability carrying amount
def remeasure(event: Event, pos: Position, revised_payments: tuple[Decimal, ...],
original_rate: Decimal, revised_rate: Decimal,
decrease_fraction: Decimal = Decimal("0")) -> dict:
rate = applicable_rate(event, original_rate, revised_rate)
if event is Event.SCOPE_DECREASE:
rou_removed = q(decrease_fraction * pos.rou) # δ · ROU
liab_removed = q(decrease_fraction * pos.liability) # δ · L
gain_loss = q(liab_removed - rou_removed) # >0 = gain, to P&L
new_liab = q(revised_liability(revised_payments, rate))
rou_retained = pos.rou - rou_removed
liab_retained = pos.liability - liab_removed
new_rou = q(rou_retained + (new_liab - liab_retained))
return {"rate_used": rate, "liability": new_liab,
"rou": new_rou, "pl_gain_loss": gain_loss}
# Every other event: ΔL adjusts the ROU asset (IFRS 16.45(b) / .39)
new_liab = q(revised_liability(revised_payments, rate))
new_rou = q(pos.rou + (new_liab - pos.liability))
pl = Decimal("0.00")
if new_rou < Decimal("0.00"): # floor at zero, spill to P&L
pl, new_rou = new_rou, Decimal("0.00")
return {"rate_used": rate, "liability": new_liab,
"rou": new_rou, "pl_gain_loss": pl}
if __name__ == "__main__":
# Rent cut on the remaining 24 months; revised rate rises to 6% (IFRS 16.45)
before = Position(rou=Decimal("210000.00"), liability=Decimal("205000.00"))
revised = tuple(Decimal("9000.00") for _ in range(24))
out = remeasure(Event.MODIFICATION, before, revised,
original_rate=Decimal("0.004074"), revised_rate=Decimal("0.004868"))
assert out["pl_gain_loss"] == Decimal("0.00") # modification: no P&L on measurement
assert out["rou"] == q(before.rou + (out["liability"] - before.liability))
print("revised liability:", out["liability"], "| revised ROU:", out["rou"])
The terminal assertions are the guardrail: a modification that is not a scope decrease must never post a gain or loss on the measurement itself, and the new asset must equal the old asset plus the exact change in the liability. If either fails, the branch or the rate is wrong.
Choosing the Branch: A Decision Tree Link to this section
Nearly every real defect is a mis-classification at the top of this tree, not an arithmetic slip further down. Walk each change through the same four questions in order.
Debugging and Precision Gotchas Link to this section
Modification logic fails in a small, recurring set of ways. Each has a deterministic fix.
-
Using the original rate on a modification. The most common defect: remeasuring a renegotiated payment stream at the commencement rate instead of a rate struck at the modification effective date. IFRS 16.45 and ASC 842-10-25-11 both require a revised rate for modifications; carrying the old rate understates or overstates the whole revised liability and every subsequent effective-interest accrual. Fix: select the rate from the event type, not from a stored field, and re-derive the revised rate from the discount rate determination working papers as of the effective date.
-
Using a revised rate on a CPI reset. The mirror error. An index or rate reassessment (IFRS 16.42–43) must keep the original locked rate — only a floating-interest-rate change moves to a revised rate. Discounting a CPI-driven payment change at a fresh rate conflates two independent movements and misstates the adjustment.
-
Booking a scope decrease to the ROU asset instead of P&L. A partial termination that simply nets the change into the right-of-use asset hides the gain or loss the standard requires (IFRS 16.46(a); ASC 842-10-25-13). Fix: branch on event type before touching balances — derecognize the proportional slice of both the asset and the liability, recognize the difference in profit or loss, and only then re-discount the retained payments.
-
Netting a scope increase against a scope decrease. A single amendment can both extend a lease and hand back space. Do not net; assess each change against the separate-lease and scope-decrease tests independently, because they route to different accounts.
-
Forgetting the classification reassessment. ASC 842 requires re-testing operating-versus-finance classification at the modification date. A schedule that keeps its old class after a term extension can flip the P&L presentation without anyone noticing.
-
Rounding the proportion before applying it. Quantizing
to two decimals before multiplying introduces cents of error into both derecognized balances and pushes the gain or loss off. Keep at full precision and quantize only the resulting money amounts.
Compliance Checklist — Before You Post a Remeasurement Link to this section
Frequently Asked Questions Link to this section
When is a lease change a separate lease rather than a remeasurement?
Only when both conditions in IFRS 16.44 and ASC 842-10-25-8 hold: the change grants an additional right of use (more assets, more space, more time that adds an asset) and the extra consideration is commensurate with the standalone price of that additional right of use, adjusted for the contract's circumstances. When both are met, the original lease is untouched and the addition is accounted for as a brand-new lease with its own commencement-date measurement and its own discount rate. If either condition fails, the change is a remeasurement of the existing liability.
Which discount rate do I use to remeasure the liability?
It depends on the event. A modification, a reassessment of the lease term or a purchase option, and a change in floating interest rates all use a revised discount rate determined at the effective date. A change in future payments driven by an index or rate — a CPI reset or a market-rent review — and a change in the amount expected under a residual value guarantee both keep the original locked rate. Selecting the rate from the event type rather than a stored default is what prevents the single most common remeasurement defect.
Does a remeasurement ever hit profit or loss?
On the measurement itself, only a decrease in scope does. For every other modification and reassessment the entire difference between the revised and prior liability adjusts the right-of-use asset, with no gain or loss — the sole exception being a reduction that would drive the asset below zero, where the excess is recognized in profit or loss. A partial termination is different: you derecognize a proportional slice of both the asset and the liability and book that difference to profit or loss before re-discounting the retained payments.
What is the difference between a modification and a reassessment?
A modification is a change to the contract's scope or consideration that was not part of its original terms — a renegotiation. A reassessment re-evaluates an estimate or judgment under the existing terms, such as concluding a renewal option is now reasonably certain, or applying a contractual CPI reset. They matter because they route differently: modifications always use a revised rate, whereas reassessments split between a revised rate (term, purchase option, floating rate) and the original locked rate (index or rate resets, residual value guarantees).
Related Link to this section
- Accounting for a lease modification in Python — the revised-rate remeasurement that adjusts the ROU asset, implemented end to end with a terminal assert.
- Partial lease termination remeasurement mechanics — the proportional ROU reduction and gain/loss recognition for a decrease in scope.
- Present value calculation logic — the discounting primitive every remeasurement re-runs on the revised payment vector.
- Discount rate determination and mapping — how the revised rate struck at the effective date is selected and locked.
- ROU asset calculation frameworks — the asset that absorbs most remeasurement offsets and is written down on a scope decrease.
- Lease liability rollforward and reconciliation — where each remeasurement appears as a non-cash movement in the disclosure.
Up: ASC 842 & IFRS 16 Core Architecture and Right-of-Use Models
Continue reading
-
Accounting for a Lease Modification in Python
Implement an ASC 842 / IFRS 16 lease modification in Python: recompute the liability at a revised discount rate, adjust the ROU asset by the delta, with Decimal precision and a terminal assert.
-
Partial Lease Termination Remeasurement Mechanics (ASC 842 / IFRS 16)
Account for a partial lease termination in Python: reduce the ROU asset proportionately to the decrease in the right of use, remeasure the liability at a revised rate, and book the gain or loss.