Skip to content

Benefit cap, targeted childcare and local CTR use the wrong UC earned income figure #1986

Description

@MaxGhenis

Problem

Three other rules use Universal Credit "earned income", and each computes it differently from the UC means test. All three predate #1949 (the fix for #1942) and are not caused by it. #1949 adds uc_individual_earned_income, the per-person figure net of the person's own tax, NI and pension contributions and before the work allowance, which is what each of them needs.

1. Benefit cap earnings exception still deducts the whole unit's tax

policyengine_uk/variables/gov/dwp/is_benefit_cap_exempt_earnings.py computes its own figure:

uc_earned = benunit.sum(employment_income + self_employment_income - income_tax - national_insurance)
earnings_threshold = 10_152

Law, UC Regs 2013 reg 82 (https://www.legislation.gov.uk/uksi/2013/376/regulation/82, read 2026-10-01):

(1) The benefit cap does not apply to an award of universal credit in relation to an assessment period where— (a) the claimant's earned income or, if the claimant is a member of a couple, the couple's combined earned income, is equal to or exceeds the amount of earnings that a person would be paid at the hourly rate set out in regulation 4 of the National Minimum Wage Regulations for 16 hours per week, converted to a monthly amount by multiplying by 52 and dividing by 12; ...

(4) "Earned income" for the purposes of this regulation does not include income a person is treated as having by virtue of regulation 62 (minimum income floor).

Counterexample (run on #1949's branch, 2025): a London couple with four children and private rent of £36,000. One partner earns £10,300; the other has no earnings and pays £923 of voluntary Class 3.

  • The model gives is_benefit_cap_exempt_earnings false, a cap reduction of £5,089.80 and UC of £21,277.40.
  • With the Class 3 set to 0 the couple is exempt and UC is £26,367.20.
  • The earner's own earned income is £10,300 in both runs, and 16 × NLW × 52 from the model's own parameter is £10,158.72.

Enhanced FRS 2026, reviewer's real runs against #1949's head:

Fix sketch: per person, max(0, earnings − uc_income_tax_on_earnings − uc_national_insurance_on_earnings − pension_contributions), summed over the unit, without the minimum-income-floor uplift (reg 82(4)); threshold from the National Living Wage parameter.

2. Targeted childcare (2-year-old offer) tests earnings after the work allowance

meets_universal_credit_criteria_for_targeted_childcare_entitlement.py compares uc_earned_income, which is net of the work allowance, with the £15,400 limit.

Law, SI 2014/2147 reg 1(3)(a) (https://www.legislation.gov.uk/uksi/2014/2147/regulation/1, read 2026-10-01):

"earned income" means income for the purposes of Chapter 2 of Part 6 of the Universal Credit Regulations 2013

The work allowance is in reg 22 (Part 4, the award calculation), not Part 6 Chapter 2.

Counterexample (run on #1949's branch, 2026): a single parent aged 30 with a child aged 2, earning £17,000, with council rent of £9,600.

  • Earned income before the work allowance is £15,759.60, over the £15,400 limit.
  • uc_earned_income is £10,635.60 after the £5,124 work allowance, so the model says the criterion is met.

Enhanced FRS 2026 (reviewer's real run): switching to the pre-work-allowance sum cuts eligible units by 102k (28 records). Entitlement amounts and household net income do not change.

Fix sketch: use the sum of uc_individual_earned_income; add YAML cases either side of the limit.

3. Local CTR schemes count UC earnings after the work allowance

council_tax_reduction/_legacy.py sets a UC claimant's income to uc_earned_income + uc_unearned_income + universal_credit. The Kingston, Merton, Newham and Westminster scheme texts, as read in review, use the Secretary of State's calculation of the claimant's income and do not subtract a work allowance. The scheme texts should be re-read when fixing.

Counterexample (reviewer's run, 2026): a London single parent with a child aged 6, earning £12,000, with council tax of £1,800. Merton, Kingston and Westminster give CTR of £1,181.16 on the model and £156.36 with earnings before the work allowance. The difference is 20% × £5,124.

Enhanced FRS 2026: all four local CTR variables total £0, so this affects household calculations only.

Notes

Activity

  1. MaxGhenis commented on Oct 1, 2026

    @MaxGhenis
    CollaboratorAuthor

    A note from #1973 (the minimum income floor fix, stacked on #1949), because it changes what uc_individual_earned_income means.

    After #1973 there are two per-person figures:

    • uc_individual_earned_income_before_mif (new): the person's actual earned income, after their own pension contributions and their own tax and NI on earnings. This is what Deduct only each person's own tax and NI on earnings from UC earned income #1949 calls uc_individual_earned_income. A trading loss counts as nil self-employed earnings (reg 57(2)).
    • uc_individual_earned_income: the same figure, or the net floor where reg 62 treats the claimant as having it.

    For the three fixes here:

    1. Benefit cap. Reg 82(4) excludes income "a person is treated as having by virtue of regulation 62". So sum uc_individual_earned_income_before_mif over the claimants, not uc_individual_earned_income. Apply the UC minimum income floor to net earned income against a net threshold #1973 itself leaves is_benefit_cap_exempt_earnings alone: that variable computes its own figure and never used the floor.
    2. Targeted childcare. SI 2014/2147 reg 1(3)(a) takes "income for the purposes of Chapter 2 of Part 6". Reg 62 sits in that Chapter, so the floored uc_individual_earned_income looks like the matching figure. That is my reading of the heading structure; please check it when fixing.
    3. Local CTR. Each scheme text decides. Where a scheme takes the Secretary of State's calculation of the claimant's income, that calculation includes the floor.

    In all three, sum over the claimants only. uc_earned_income currently sums every member of the benefit unit, including dependants; #1973's couple rule uses at most the two eldest is_uc_claimant members.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions