You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Fix import/no-cycle that are currently silent #99650
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.
@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)
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:
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
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.
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:
Activity
LukasMod commentedon Aug 27, 2026
@MelvinBot assign @roryabraham and @LukasMod here
MelvinBot commentedon Aug 27, 2026
🤖 Done — assigned
roryabrahamandLukasModto this issue.view run
LukasMod commentedon Aug 28, 2026
1 PR: #99670 is ready for review: 534 findings reduced to 478 (-56)
thelullabyy commentedon Aug 30, 2026
@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?
LukasMod commentedon Aug 31, 2026
@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)
roryabraham commentedon Aug 31, 2026
PR 1 merged. Requested @thelullabyy review on parts 2 and 3
93 remaining items
melvin-bot commentedon Oct 12, 2026
@thelullabyy Whoops! This issue is 2 days overdue. Let's get this updated quick!
melvin-bot commentedon Oct 14, 2026
@thelullabyy Huh... This is 4 days overdue. Who can take care of this?
melvin-bot commentedon Oct 15, 2026
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.
melvin-bot commentedon Oct 16, 2026
@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:
melvin-bot commentedon Oct 16, 2026
@thelullabyy Still overdue 6 days?! Let's take care of this!
thelullabyy commentedon Oct 18, 2026
In progress
LukasMod commentedon Oct 20, 2026
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:
isExpensifyTeampressLockedBankAccountout of BankAccountscore.tsleaf + approvals paramgetAllSortedTransactionscache, now paramroryabraham commentedon Oct 20, 2026
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.
melvin-bot commentedon Oct 21, 2026
@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: