Why Do Production Codebases Have 400+ eslint-disable Comments (And Is That Bad?)
Problem
When I looked at Claude Code’s leaked source code, I saw 460 eslint-disable comments. My first reaction was: is this a code quality problem?
A Reddit thread exploded with debate. Some developers said this proves “code quality doesn’t matter.” Others argued it shows “pragmatic engineering.”
So I asked myself: when does suppressing lint rules make sense, and when is it just lazy?
What I Found
I started analyzing when eslint-disable appears in production code. Here are the patterns I saw:
Pattern 1: Third-Party API Weirdness
// Third-party SDK returns `any` for error responses// Tracking issue: https://github.com/vendor/sdk/issues/123// eslint-disable-next-line @typescript-eslint/no-explicit-anyconst errorResponse: any = sdk.parseError(rawError);This is pragmatic. The vendor’s types are wrong. I can either:
- Wait for them to fix it (maybe never)
- Cast to
unknownand add runtime checks (adds complexity) - Suppress the rule with documentation (what I did)
I chose option 3 because the fix is tracked, and the scope is limited.
Pattern 2: Gradual Migration
// TODO: Remove when migration to strict mode completes// Tracked in JIRA-4521// eslint-disable-next-line @typescript-eslint/no-unsafe-assignmentconst legacyData = oldSystem.getData();This is also valid. I’m migrating 50,000 lines of code. I can’t do it all at once. Each disable has:
- A TODO comment explaining why
- A tracking ticket
- A plan to remove it
Pattern 3: Framework Requirements
// Next.js requires getServerSideProps to be exported// eslint-disable-next-line import/no-default-exportexport default function Page() { return <div>Content</div>;}
export async function getServerSideProps() { // ...}The framework demands this pattern. I can’t change Next.js. The disable is intentional.
Pattern 4: Intentional Edge Cases
// Intentionally catching and ignoring specific errors// eslint-disable-next-line no-emptycatch (e) { // Network timeouts are expected and don't need logging}This one required a comment explaining why the rule is disabled. Without the comment, it looks lazy.
When It’s Lazy
Now let me show the patterns that ARE problematic:
Anti-Pattern 1: No Explanation
// eslint-disable-next-line @typescript-eslint/no-explicit-anyfunction process(data: any) { return data.value;}Why is any needed here? No comment. No tracking. No plan. This is lazy.
Anti-Pattern 2: File-Level Disables
/* eslint-disable */// Entire 500-line file with no lint checkingThis is the worst. One disable for an entire file? I’ve seen files with this at the top and no one knows why. The original author left years ago.
Anti-Pattern 3: Copy-Paste Without Understanding
// Copied from Stack Overflow// eslint-disable-next-line react-hooks/exhaustive-depsuseEffect(() => { fetchData();}, []);I copied this. I don’t know why the dependency array is empty. I just wanted the warning to go away.
Anti-Pattern 4: Disabling Instead of Fixing
// Too lazy to refactor// eslint-disable-next-line @typescript-eslint/no-unused-varsfunction oldFunction(notUsed: string, alsoNotUsed: number) { // ...}The function has unused parameters. Instead of fixing the signature, I suppressed the warning.
What ESLint Recommends
ESLint’s official guidance says disables should be:
- Restricted - Use
noInlineConfig: falsein production - Documented - Always add a comment explaining why
- Temporary - Link to an issue or TODO for removal
- Reviewed - Require approval in code review
Here’s how I configure this:
{ "rules": { "@typescript-eslint/no-explicit-any": "error", "@typescript-eslint/no-unused-vars": ["error", { "argsIgnorePattern": "^_" }] }, "overrides": [ { "files": ["**/*.ts"], "rules": { "no-restricted-syntax": [ "error", { "selector": "CallExpression[callee.name='disableEsLint']", "message": "Use eslint-disable comments with caution and always add an explanation" } ] } } ]}Metrics That Matter
I started tracking eslint-disable usage across projects:
| Count per 10K LOC | Assessment | Action |
|---|---|---|
| < 50 | Normal | Monitor |
| 50-100 | Review needed | Audit for documentation |
| > 100 | Concern | Require justification per disable |
But count alone isn’t enough. I also track:
#!/bin/bash
# Count total disablesTOTAL=$(grep -r "eslint-disable" src/ | wc -l)
# Count those with explanations (preceding comment line)DOCUMENTED=$(grep -B1 "eslint-disable" src/ | grep "// " | wc -l)
# Calculate percentage undocumentedUNDOCUMENTED=$((TOTAL - DOCUMENTED))PERCENTAGE=$((UNDOCUMENTED * 100 / TOTAL))
echo "Total: $TOTAL"echo "Documented: $DOCUMENTED"echo "Undocumented: $UNDOCUMENTED ($PERCENTAGE%)"Running this on a recent project:
$ ./eslint-disable-audit.shTotal: 87Documented: 52Undocumented: 35 (40%)40% undocumented is too high. I set a threshold: if > 30% are undocumented, the PR gets blocked.
Common Rules That Get Disabled
I analyzed which rules I disable most:
| Rule | Valid Reason? | Example Justification |
|---|---|---|
@typescript-eslint/no-explicit-any | Often yes | Third-party SDK lacks types |
@typescript-eslint/no-unused-vars | Rarely | Usually means dead code or wrong signature |
no-console | Sometimes | CLI tools need console output |
@typescript-eslint/naming-convention | Sometimes | API requirements from external system |
react-hooks/exhaustive-deps | Sometimes | Intentional empty deps for mount-only effect |
For no-explicit-any, I created a pattern:
// Instead of disabling, create a branded typetype VendorResponse = unknown & { __brand: "VendorResponse" };
// Force explicit handlingfunction parseVendorResponse(data: unknown): VendorResponse { if (typeof data !== "object" || data === null) { throw new Error("Invalid response"); } return data as VendorResponse;}This removes the need for eslint-disable entirely.
The Reddit Debate
The Reddit thread on Claude Code’s 460 disables revealed two camps:
Camp 1: “This is fine”
“There’s only one thing better than pristine code: code in production. Ship it.” - Senior engineer with 15 years experience
“That’s what new starters don’t get. They see these and think it’s bad code. They don’t see the trade-offs we made.” - Tech lead at Series B startup
Camp 2: “This is tech debt”
“Every disable is a compromise. If you have 460 compromises, maybe your standards are too high or your team is too rushed.” - Staff engineer at Big Tech
“Blanket disables without explanation are problematic. It’s not the count, it’s the lack of documentation.” - Open source maintainer
I think both are right. The count doesn’t matter. The intention does.
What I Do Now
After this analysis, I updated my team’s workflow:
- Every disable needs a comment - Not just the rule name, but why
- Link to an issue - For non-trivial disables, create a tracking ticket
- Review in PRs - Disables get extra scrutiny in code review
- Monthly audits - Run the audit script and address undocumented disables
Here’s a template I use:
// REASON: [Why this rule is disabled]// TRACKING: [Issue/PR URL or "permanent" if intentional]// ALTERNATIVES CONSIDERED: [What else we tried]// eslint-disable-next-line @typescript-eslint/no-explicit-anyExample:
// REASON: Vendor SDK v2.x returns untyped error objects// TRACKING: https://github.com/vendor/sdk/issues/1234// ALTERNATIVES CONSIDERED: Casting to unknown + runtime checks (too verbose)// eslint-disable-next-line @typescript-eslint/no-explicit-anyfunction handleVendorError(error: any): ProcessedError { return { code: error.code ?? "UNKNOWN", message: error.message ?? "An error occurred" };}Summary
In this post, I analyzed when eslint-disable comments are pragmatic vs. lazy. The key point is not how many disables exist, but whether each one is intentional, documented, and tracked.
The 460 disables in Claude Code’s source don’t automatically mean bad code. What matters is:
- Is there a reason documented?
- Is there a plan to fix (if applicable)?
- Is the scope limited (line-level vs file-level)?
If I can answer “yes” to those questions, the disable is acceptable. If not, it’s technical debt.
Final Words + More Resources
My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me
Here are also the most important links from this article along with some further resources that will help you in this scope:
- 👨💻 ESLint Inline Configuration Comments
- 👨💻 TypeScript ESLint Documentation
- 👨💻 Reddit Discussion: Claude Code Leaked Source
Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!
Comments