Skip to content

Fix import/no-cycle that are currently silent #99650

Open

Description

@LukasMod

Background

While preparing the ESLint to Oxlint migration, a batch of violations surfaced that ESLint does not report
today. import/no-cycle is the largest of them by a wide margin: 534 circular imports across 148 files
in src/
, all of them real.

The rule has been in our ESLint config for years with maxDepth: '∞', and it reports 0. ESLint's
resolver never resolves the @src/..., @libs/... and @components/... aliases, so it never builds a
module graph and has nothing to check. Oxlint reads tsconfig.json, resolves the aliases, and sees the
graph.

Fixing what the new linter found is a prerequisite for the migration. The day Oxlint becomes a blocking
check, these 534 findings become 534 hard errors, so the cleanup has to land first and on its own schedule.

Cycle path is a symptom, not a work item. Break the cycle it draws and the finding often
survives, now drawing a different cycle through the same import. One row fixed can reappear as another cycle issue re-reported.

The numbers

Findings 534
Files involved 148, all under src/
Mutually dependent clusters 6, largest 116 files
Import edges inside those clusters 537
Import edges that must break to reach 0 findings 54
Shortest and longest cycle 2 and 39 modules

Definition of done

  • A clean Oxlint run reports 0 import/no-cycle findings.
  • No eslint-disable or oxlint-disable comment is added for import/no-cycle anywhere. A suppressed cycle
      is still a cycle and still carries costs.

How to validate numbers

List generated on POC oxlint branch #98027
To reproduce use .oxlintrc.no-cycle.json and run command:

npx oxlint . -c .oxlintrc.no-cycle.json -f json > oxlint-no-cycle-findings.json

Current results:
oxlint-no-cycle-findings.json

Issue OwnerCurrent Issue Owner: @thelullabyy

Activity

  1. LukasMod commented on Aug 27, 2026

    @LukasMod
    ContributorAuthor
  2. MelvinBot commented on Aug 27, 2026

    @MelvinBot
    Contributor

    🤖 Done — assigned roryabraham and LukasMod to this issue.


    view run

  3. LukasMod commented on Aug 28, 2026

    @LukasMod
    ContributorAuthor

    1 PR: #99670 is ready for review: 534 findings reduced to 478 (-56)

  4. thelullabyy commented on Aug 30, 2026

    @thelullabyy
    Contributor

    @roryabraham @LukasMod Since I reviewed the first PR, could you please assign me the assign so that I will be assigned on the part 2 PR?

  5. LukasMod commented on Aug 31, 2026

    @LukasMod
    ContributorAuthor

    @thelullabyy Sorry but I don't have such permissions to assign someone. Lets wait for @roryabraham to decide that.
    In a meantime I prepared PR2: #99768 478 -> 458 (-20)

  6. roryabraham commented on Aug 31, 2026

    @roryabraham
    Contributor

    PR 1 merged. Requested @thelullabyy review on parts 2 and 3

  7. added
    ReviewingHas a PR in review
    and removed
    ReviewingHas a PR in review
    on Sep 1, 2026
  8. 93 remaining items

  9. melvin-bot commented on Oct 12, 2026

    @melvin-bot

    @thelullabyy Whoops! This issue is 2 days overdue. Let's get this updated quick!

  10. melvin-bot commented on Oct 14, 2026

    @melvin-bot

    @thelullabyy Huh... This is 4 days overdue. Who can take care of this?

  11. melvin-bot commented on Oct 15, 2026

    @melvin-bot

    ⚠️ Looks like this issue was linked to a Deploy Blocker here

    If you are the assigned CME please investigate whether the linked PR caused a regression and leave a comment with the results.

    If a regression has occurred and you are the assigned CM follow the instructions here.

    If this regression could have been avoided please consider also proposing a recommendation to the PR checklist so that we can avoid it in the future.

  12. melvin-bot commented on Oct 16, 2026

    @melvin-bot

    @thelullabyy

    The solution for this issue has been 🚀 deployed to production 🚀 in version 9.5.12-1 and is now subject to a 7-day regression period 📆. Here is the list of pull requests that resolve this issue:

  13. melvin-bot commented on Oct 16, 2026

    @melvin-bot

    @thelullabyy Still overdue 6 days?! Let's take care of this!

  14. thelullabyy commented on Oct 18, 2026

    @thelullabyy
    Contributor

    In progress

  15. LukasMod commented on Oct 20, 2026

    @LukasMod
    ContributorAuthor

    All 18 parts merged.
    Today I checked oxlint results and we have new issues, preparing new parts to reduce it (from the easiest)

    Current main (eslint-disable no-cycle comments ignored): 162 findings
    If we manage to go there there will be ~13 left, related to ReportActionsUtils, ReportUtils and TransactionUtils.

    Incremental Δ = measured on the stacked worktree in this order. Standalone Δ = PR alone on main.

    Current plan:

    # PR standalone incremental (running total) effort risk Onyx cache
    19 RenderHTML gets renderers from context -60 -60 (102) S low none
    20 Workflow rules Onyx-data builders to a leaf -44 -44 (58) S low none
    21 Small leaves: Search 2-cycle, DistanceRequestUtils, isExpensifyTeam -12 -13 (45) S low none
    22 ReportNameUtils stops importing ModifiedExpenseMessage -5 -5 (40) S/M low none
    23 pressLockedBankAccount out of BankAccounts -3 -5 (35) M low param-pass of BANK_ACCOUNT_LIST (maybe we could use Onyx.get here)
    24 ReportUtils stops importing ViolationsUtils -5 -4 (31) M low none moved
    25 TransactionUtils core.ts leaf + approvals param -7 -18 (13) M med approvals took getAllSortedTransactions cache, now param
  16. roryabraham commented on Oct 20, 2026

    @roryabraham
    Contributor

    thanks for the updated @LukasMod. We can also start working on #104516, add current violations to the seatbelt file, then continue on this to ratchet them down. That way, we don't end up with too many new violations being added in the meantime.

  17. melvin-bot commented on Oct 21, 2026

    @melvin-bot

    @thelullabyy

    The solution for this issue has been 🚀 deployed to production 🚀 in version 9.5.15-3 and is now subject to a 7-day regression period 📆. Here is the list of pull requests that resolve this issue:

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

Metadata

Metadata

Labels

ReviewingHas a PR in reviewSkip PaymentSkips all the payment process steps for an issue. Use it for fixed-price projects.WeeklyKSv2

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions