The model applies the next tier's lower percentage to California's child and dependent care credit at AGI of $40,000, $70,000 and $100,000

Open Beginner friendly
#10,915 0 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 2 days

Nobody has claimed this yet.

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
82/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
python
Domain
backend

Research direction

The bad lookup is in ca_cdcc.py at line 17, where p.rate.calc(agi) reads the bracket scale in rate.yaml. Run the reproduction script in the issue to compare the right=False and right=True rates at the three endpoint AGIs. Done when AGIs of $40,000, $70,000 and $100,000 get the lower tier's rate and YAML tests pin those three values.

Written by the indexing model from the issue text.

Description

The Legislature set California's percentage of the federal credit at 50% for adjusted gross income (AGI) of $40,000 or less, 43% over $40,000 through $70,000, and 34% over $70,000 through $100,000. The Franchise Tax Board applies these tiers to federal AGI. The model puts each endpoint in the next tier: it applies 43% at $40,000, 34% at $70,000 and 0% at $100,000. Only filers with federal AGI equal to one of those three amounts get the wrong percentage.

Example

For example, a head of household in California has one child aged 3, $5,000 of child care costs and wages as their only income in 2025. On the 2025 FTB 3506, the filer multiplies line 6, here the $3,000 one-child limit, by the federal decimal on line 7 to get line 8, then multiplies line 8 by California's decimal on line 9:

Federal AGI Line 8 Line 9 Credit on FTB 3506 Model's ca_cdcc
$40,000 $660 .50 $330 $283.80
$70,000 $600 .43 $258 $204.00
$100,000 $600 .34 $204 $0

At $39,999 and $40,001, the model applies the line 9 chart's 50% and 43%, so it misplaces only the endpoints. At $40,000, this filer owes no California tax after exemption credits either way. At $70,000 the model gives $239.19 of California income tax; with the $258 credit from FTB 3506 it would give $185.19, $54 less. At $100,000 it gives $2,156.29, and with the $204 credit it would give $1,952.29.

What California law says

In SB 86 (2011), section 2, the Legislature amended Revenue and Taxation Code section 17052.6. In subdivision (b)(2), it set 50% for AGI of "$40,000 or less", 43% "[o]ver $40,000 but not over $70,000" and 34% "[o]ver $70,000 but not over $100,000". The Franchise Tax Board prints the same chart for line 9 in its 2025 FTB 3506 instructions and lets a filer claim the credit with federal AGI of $100,000 or less.

Where it sits in the code

In ca_cdcc.py, line 17, the model calls p.rate.calc(agi) on the single-amount scale in rate.yaml, lines 2-21. With the default right=False in calc, the model puts an AGI equal to a threshold in the tier that starts there. See #10072 and #10177 for the same pattern in New Jersey's and West Virginia's tables.

Reproduce

At commit 935b24ff:

import numpy as np
from policyengine_us import CountryTaxBenefitSystem, Simulation

YEAR = 2025
for wages in [40_000, 70_000, 100_000]:
    sim = Simulation(situation={
        "people": {
            "parent": {"age": {YEAR: 35}, "employment_income": {YEAR: wages}},
            "child": {"age": {YEAR: 3}},
        },
        "tax_units": {"tax_unit": {
            "members": ["parent", "child"],
            "filing_status": {YEAR: "HEAD_OF_HOUSEHOLD"},
            "tax_unit_childcare_expenses": {YEAR: 5_000},
        }},
        "spm_units": {"spm_unit": {"members": ["parent", "child"]}},
        "families": {"family": {"members": ["parent", "child"]}},
        "marital_units": {
            "parent": {"members": ["parent"]},
            "child": {"members": ["child"]},
        },
        "households": {"household": {
            "members": ["parent", "child"],
            "state_code": {YEAR: "CA"},
        }},
    })
    print(wages)
    for variable in [
        "adjusted_gross_income",
        "ca_federal_cdcc",
        "ca_cdcc",
        "ca_income_tax",
    ]:
        print(f"  {variable}: {float(sim.calculate(variable, YEAR)[0]):,.2f}")

rate = CountryTaxBenefitSystem().parameters(f"{YEAR}-01-01").gov.states.ca.tax.income.credits.child_dependent_care.rate
agis = np.array([39_999.0, 40_000.0, 40_001.0, 70_000.0, 70_001.0, 100_000.0, 100_001.0, -5_000.0])
print("   AGI         ", agis.tolist())
print("   right=False ", rate.calc(agis).tolist())
print("   right=True  ", rate.calc(agis, right=True).tolist())

Output:

40000
  adjusted_gross_income: 40,000.00
  ca_federal_cdcc: 660.00
  ca_cdcc: 283.80
  ca_income_tax: 0.00
70000
  adjusted_gross_income: 70,000.00
  ca_federal_cdcc: 600.00
  ca_cdcc: 204.00
  ca_income_tax: 239.19
100000
  adjusted_gross_income: 100,000.00
  ca_federal_cdcc: 600.00
  ca_cdcc: 0.00
  ca_income_tax: 2,156.29
   AGI          [39999.0, 40000.0, 40001.0, 70000.0, 70001.0, 100000.0, 100001.0, -5000.0]
   right=False  [0.5, 0.43, 0.43, 0.34, 0.34, 0.0, 0.0, 0.5]
   right=True   [0.5, 0.5, 0.43, 0.43, 0.34, 0.34, 0.0, 0.5]

Possible fix

Call p.rate.calc(agi, right=True) on line 17. The first threshold sits at negative infinity, so the change moves only the three endpoints, and a YAML test at each of $40,000, $70,000 and $100,000 would pin them.

Dominant language
Python
Stars
171
Forks
220
Avg merge
4d 13h
Merged PRs (30d)
291

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from PolicyEngine/policyengine-us

All issues in PolicyEngine/policyengine-us

Similar issues

More Python issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.