Skip to content

Extracting Limitation of Liability Caps From a Contract

10 min read · updated August 11, 2026

Asking a model for “the liability cap” and getting back a dollar figure means one of two things: the contract stated one, or the model invented one. The second is more common, because most caps are expressed as a multiple of fees that have not been paid yet.

The cap has a measure, not a value

Caps come in a small number of shapes, and the shape is the field:

  • A fixed amount. “shall not exceed $500,000”. The only one that extracts as a number.
  • A backward-looking fee window. “the fees paid or payable in the twelve months preceding the event giving rise to the claim”. The value depends on a date that is unknown when you extract.
  • A multiple. “two times the fees paid in the preceding twelve months”, or of annual contract value, which is a different base.
  • A greater-of or lesser-of. “the greater of $100,000 and the fees paid in the preceding twelve months” — a floor and a formula in one expression.
  • Total fees under the agreement, uncapped by any window, which grows over the life of a long contract.

Two further axes cut across all of them. Per claim or aggregate decides whether the number is a ceiling on one dispute or on the whole relationship, and the word “aggregate” is often the only signal. Mutual or one-way decides whether both parties enjoy the cap; a clause capping “the Supplier’s liability” with no reciprocal sentence is a different commercial position from a mutual one, and the difference is a single possessive.

Extract the cap as an expression with named inputs rather than as a scalar:

{
  "cap": {
    "form": "greater_of",
    "operands": [
      { "form": "fixed", "amount": 100000, "currency": "USD" },
      { "form": "fee_window",
        "multiple": 1,
        "window_months": 12,
        "window_anchor": "event_giving_rise_to_claim",
        "fee_basis": "paid_or_payable" }
    ],
    "scope": "aggregate",
    "applies_to": ["supplier", "customer"],
    "verbatim": "..."
  }
}

What survives the cap

The cap sentence is rarely the whole clause. Immediately after it comes a sentence beginning “nothing in this Agreement shall limit liability for” or “the foregoing shall not apply to”, and the list that follows is not capped. Common members include a party’s indemnity obligations, breach of confidentiality, infringement of intellectual property rights, breach of data protection obligations, fraud, wilful misconduct and gross negligence, the customer’s obligation to pay fees, and death or personal injury caused by negligence — the last of which some jurisdictions do not permit to be excluded at all, which is why it appears almost reflexively in English-law drafting.

Two structures make this harder than reading a list. The first is the supercap: a carve-out that is not uncapped but capped at a higher, separately stated figure — “save that liability for breach of Clause 12 shall not exceed five times the fees”. That is a second cap expression with its own scope, and a schema with one cap object cannot hold it. Model caps as an array with an applies_to_categories field on each.

The second is that the exclusion of indirect and consequential loss is a distinct provision that people habitually bundle into “the liability clause”. It removes whole categories of damage rather than capping an amount, its list is its own vocabulary — loss of profit, loss of revenue, loss of anticipated savings, loss of goodwill, loss of data — and whether loss of profit is named matters commercially. Keep it in its own field, with its own verbatim span and its own carve-outs, because it is separately negotiated and separately queried.

Working a fee-multiple cap

Take a clause capping aggregate liability at the fees paid in the twelve months preceding the event giving rise to the claim, and an agreement with a stated fee schedule. All figures below are assumptions chosen to show the arithmetic, not data from any contract.

Assume the subscription fee is $9,000 per month, that a professional services statement of work was invoiced once at $40,000 in March 2025, that the customer paid every subscription invoice on time, and that the event giving rise to the claim occurred on 2026-04-10. The window is 2025-04-10 to 2026-04-10.

window            = 2025-04-10 .. 2026-04-10
subscription      = 12 x 9,000            = 108,000
services invoice  = 40,000, invoiced 2025-03-xx  -> outside window
cap (fees paid in window)                 = 108,000

Now change one assumption. If the clause says “paid or payable” rather than “paid”, an invoice issued inside the window but not yet settled counts, and the figure rises. If the base is “fees paid under this Agreement” and the statement of work is executed under the same master agreement, the $40,000 may fall inside a total-fees measure while remaining outside a twelve-month one. If the clause reads “annual fees” rather than “fees paid”, the base is the contracted annual value — $108,000 here by coincidence, but a different number entirely if the customer took a mid-term upgrade.

That sensitivity is the argument for extracting fee_basis, window_months and window_anchor as separate fields instead of a phrase. Each of them changes the answer independently, and a stored string cannot be recomputed when the fee data is corrected.

When the cap cannot be evaluated yet

A backward-looking window anchored on the event giving rise to the claim has no value until there is a claim. This is the single most common way a contract-review pipeline produces confident nonsense: the schema demands a number, the model supplies one by annualising whatever fee it can see, and the figure looks entirely reasonable in a review UI.

The fix is a schema that permits the honest answer. Make the evaluated amount optional and add an explicit status — evaluable, needs_fee_data, needs_claim_date — so that an unevaluated cap is a valid, complete extraction rather than a hole somebody feels obliged to fill, which is the pattern set out in handling a missing required field. The published page on designing schemas a model can actually satisfy makes the general version of this argument: a required field with no honest value is an instruction to fabricate.

Where it goes wrong

  • Currency is not stated in the clause. Caps frequently say “the fees” and leave currency to the order form. An extraction that assumes the document’s locale gets it wrong on cross-border agreements.
  • Two caps for two products. A master agreement with several order forms may cap per order form. The clause reads as one cap; the operative scope is per contract document.
  • The carve-out list is negated twice. “Nothing shall limit liability for X, save that this shall not apply where Y” is an exception to an exception. Preserve the verbatim span; do not let a summary flatten it.
  • All-caps blocks. Liability and warranty language is often set in capitals for the same reason discussed in the warranty disclaimer page, and capitalised text both reads worse for OCR and sometimes trips case-sensitive clause detectors.
  • The cap in the order form overrides the master. An order form line reading “Liability cap: $250,000 (notwithstanding Section 11)” is the operative cap. Extraction over a single document cannot see it, which is a corpus design problem rather than a prompting one.