Skip to content

S-Corp/partnership losses excluded from AGI due to max(0,...) in irs_gross_income #7461

@PavelMakarchuk

Description

@PavelMakarchuk

Summary

irs_gross_income.py clips all income sources to $0 with max_(0, ...), which means negative partnership_s_corp_income (S-Corp and partnership losses) never reduces gross income or AGI. There is no separate mechanism to deduct these losses, so they are silently dropped.

The code

irs_gross_income.py (line 19):

for source in sources:
    # Add positive values only - losses are deducted later.
    total += not_dependent * max_(0, add(person, period, [source]))

The comment says "losses are deducted later," but loss_ald.py only deducts:

  • self_employment_income losses
  • limited_capital_loss (capital losses, capped at $3,000)

loss_ald.py:

def formula(tax_unit, period, parameters):
    filing_status = tax_unit("filing_status", period)
    max_loss = parameters(period).gov.irs.ald.loss.max[filing_status]
    person = tax_unit.members
    indiv_se_loss = max_(0, -person("self_employment_income", period))
    self_employment_loss = tax_unit.sum(indiv_se_loss)
    limited_capital_loss = tax_unit("limited_capital_loss", period)
    return min_(max_loss, self_employment_loss + limited_capital_loss)

There is no deduction path for partnership_s_corp_income losses. They are excluded from gross income by the max_(0, ...) and never recovered.

What the IRS rules say

S-Corp losses pass through to shareholders under 26 USC §1366(a) and flow through Schedule E Part II → Schedule 1 line 5 → Form 1040, directly reducing AGI. Allowable losses are subject to four sequential limitations:

  1. Basis limitation — §1366(d): losses limited to stock + debt basis
  2. At-risk limitation — §465: losses limited to amount at risk
  3. Passive activity limitation — §469: passive losses can only offset passive income (but materially participating shareholders' losses are nonpassive and fully deductible)
  4. Excess business loss limitation — §461(l): for 2021, $262K single / $524K MFJ cap (losses beyond this become NOL carryforwards)

After these limitations, the remaining loss reduces AGI. Since PolicyEngine doesn't have inputs for basis, at-risk amounts, or passive/active classification, a reasonable assumption (used by TAXSIM) is that the reported value is already net of all limitations.

TAXSIM's approach (for reference)

TAXSIM includes negative scorp directly in Schedule E and total income with no clipping:

! taxsim.f line 31040-31041
schede = data(74)+data(75)+data(76)+data(77)+data(78)+data(79) + data(213)

! line 31054-31056: ti includes schede
ti = capgn + data(11) + divall + ... + schede + (d17-data(213)) + ...

! line 31122
agi = ti - adjust

With the comment at lines 31136-31137:

c Passive loss limitations apply only to rental losses
c Non-rental losses are considered allowable if reported by the SOI

Empirical impact

In a comparison of 1,000 CPS households (2021), all 73 records with negative S-Corp income show PE AGI higher than TAXSIM AGI by approximately |scorp|:

Metric Value
Records affected 73 of 1,000 (all negative scorp)
AGI diff / |scorp| ratio 1.00 for most records
Mean absolute AGI difference $2.8M
Mean absolute fiitax difference $147K

Examples:

taxsimid scorp PE AGI - TAXSIM AGI
75300 -$51,506,712 +$51,506,712
112263 -$25,864,222 +$25,864,222
79995 -$6,989,538 +$6,989,538
78933 -$122 +$122

Suggested fix

Add partnership_s_corp_income losses to loss_ald.py, subject to the existing §461(l) excess business loss cap:

indiv_ps_loss = max_(0, -person("partnership_s_corp_income", period))
partnership_s_corp_loss = tax_unit.sum(indiv_ps_loss)
return min_(max_loss, self_employment_loss + limited_capital_loss + partnership_s_corp_loss)

This assumes the input value is already net of basis, at-risk, and passive activity limitations (matching TAXSIM's assumption and consistent with how self_employment_income losses are already handled).

Alternatively, the max_(0, ...) in irs_gross_income.py could be removed for this source, but the loss_ald approach maintains consistency with how SE losses are handled and preserves the §461(l) cap.

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