Why developers hate linters?

Aravind Putrevu

by Aravind Putrevu

January 08, 2025

7 min read

Cover image for article: Why developers hate linters?

Disclaimer: I get it; some of you out there are Linters' biggest fans. But to be clear, this is my humble opinion, not a call to arms!

As a senior developer who has worked in a variety of teams, tech stacks, and organizational cultures, I’ve had my fair share of experiences with linters. A linter is a tool that programmatically checks source code for stylistic consistency, potential errors, or departures from a predetermined set of rules.

This sounds like a great idea on paper: automate the nagging details of the coding style, catch issues before they become defects, and keep the codebase tidy. In practice, the relationship between developers and linters is far more complicated.

Why does this happen? After all, we’re talking about something that should, in theory, help developers write better code. To understand why some developers often end up viewing linters as more of a hindrance than a help, we need to dig deeper into the cultural, psychological, and practical realities of software development.

Let’s closely examine the underlying reasons for the tension, drawing on some industry sentiments and the lived experiences of engineers on the ground.

Warning Fatigue and False Positives

The concept of “warning fatigue” is well-known in many fields. When people receive too many non-critical or erroneous warnings, they start ignoring them altogether. The same happens with linters. If a linter is configured too strictly, it might flag many issues, many of which are superficial and don’t represent real bugs. Over time, developers start to tune out these warnings. Eventually, meaningful alerts might be lost in the noise.

False positives are where the linter incorrectly flags a code snippet or a pattern that is actually fine. A developer can think the tool isn’t configured well or useful with each false positive fix.

{
  "rules": {
    // Overwhelming style rules
    "quotes": ["error", "single"],
    "semi": ["error", "always"],
    "indent": ["error", 2],
    "comma-dangle": ["error", "always-multiline"],
    "arrow-parens": ["error", "always"],
    "max-len": ["error", { "code": 80 }],

    // Actually important rules buried in noise
    "no-eval": "error",
    "no-implied-eval": "error",
    "security/detect-object-injection": "error",

    // False positive generators
    "no-unused-vars": "error",
    "no-unreachable": "error",
    "no-unsafe-optional-chaining": "error",
    "typescript-no-unused-vars": "error",
    "@typescript-eslint/no-unused-vars": "error"
  }
}

Frankly, false positives and noise from linters are the least of the troubles; linters can cause team friction by creating a style debate.

New Sources of Style Debates (Bikeshedding)

One of the often-touted benefits of linters is that they supposedly end debates about code style. In reality, they can just shift the debate from “What style do we use?” to “Which rules do we enable or disable?”

Teams can spend enormous amounts of time arguing over style guide configurations. Should we use trailing commas or not? Should we enforce camelCase, snake_case, or PascalCase for certain identifiers? Should lines be limited to 80 characters, 100, or 120?

Here's a typical scene in many development teams: A developer submits a critical authentication function for review:

def authenticate_user(user_data):
    username = user_data['username']     # Linter: line too long (81 chars)
    password = user_data['password']     # Linter: prefer single quotes

    if username and password:            # Linter: missing whitespace
        result= query_db(                # Linter: missing space around operator
            f"SELECT * FROM users WHERE username='{username}' AND password='{password}'" 
        )                               # Linter: trailing whitespace
        return result
    return None                         # Linter: inconsistent return statements

This can lead to what is known as “bikeshedding”—the phenomenon where groups spend disproportionate time discussing trivial details instead of focusing on more significant issues.

Instead of eliminating debates, linters often just turn them into religious wars over rule sets. And once a certain style guide is chosen—often an off-the-shelf configuration like the Airbnb Style Guide—there can be pushback when team members try to tweak it. The environment can become rigid and dogmatic, further souring developers’ relationships with the tool.

Inflexible Rules and Contextual Nuance

A key limitation of linters is their inability to understand context. Code often has nuances that escape simplistic rule-based tools. For example, a particular code structure might violate a stylistic rule but make perfect sense in a specific scenario—perhaps it handles an edge case elegantly. The linter, however, doesn’t care about this context. It just sees a rule violation.

Consider this matrix operation where readability improves when it is vertical aligned:

def transform_matrix(matrix):
    return [
        [1, 0, 0],    # Linter: trailing whitespace
        [0, 1, 0],    # Linter: trailing whitespace
        [0, 0, 1]     # Linter: trailing whitespace
    ]

    # What the linter forces you to write:
    return [[1,0,0],[0,1,0],[0,0,1]]  # "Fixed" but less readable

As a result, developers sometimes find themselves writing awkward, less-intuitive code just to appease the linter.

The Illusion of Automatic Perfection

Another subtle issue is the risk that teams start treating the linter as a silver bullet for code quality. The presence of a linter and a “clean” linting report might foster a false sense of security. Managers or junior developers might assume that because the code passes all lint checks, it must be good. In reality, linters are just one small tool in a larger toolbox.

When teams focus overly on linting, they may neglect other essential practices like peer reviews, architectural reviews, and thorough testing. As a result, some genuinely critical problems slip through the cracks because everyone was too busy ensuring that we followed a a specific coding style. Experienced developers often resent the notion that a set of automated-style checks could replace human judgment and good engineering practices.

Perceived Abuse of Power and Control

The feeling that linters can be used as a tool of control. If a team or a lead developer sets up extremely strict rules and won’t budge, others can feel micromanaged. Every minor commit leads to lint failures and demands for stylistic changes. Over time, this creates a hostile environment where developers feel their expertise and professional judgment aren’t trusted. Instead of collaboration, the coding style becomes a battleground for power dynamics.

This resentment might not be rational in every case, but it exists. The line between helpful guidance and micromanagement can be thin. Development teams thrive on trust, respect, and autonomy. Linters, when misused, can undermine all three.

The Loss of Creative Freedom

“Programming is the art of telling another human being what one wants the computer to do. We should continually strive to transform every art into a science: in the process, we advance the art” - Donald Knuth in Art of Programming.

Software development, at its core, blends technical precision with creative expression. Developers often craft their code like artisans, choosing specific ways to structure and style their work that reflect their understanding and experience. But when linters enforce rigid rules, they can stifle this creative element.

Imagine refactoring a complex code snippet (say a function) to readable, maintainable code, only to have a linter force you to break it up and reshape it according to inflexible rules. The code becomes less a reflection of your thought process and more a product of automated formatting. While consistency has its merits, especially in team settings, this mechanical enforcement can diminish the craft of coding and frustrate experienced developers who have developed their own effective coding styles.

Balancing the Benefits and Drawbacks

Despite all these reasons, it’s important to acknowledge that linters aren’t inherently evil. They can be incredibly valuable tools when used thoughtfully. The trick lies in striking a balance: use linters to catch genuine errors or enforce a minimal set of style rules that genuinely improve readability and consistency.

Don’t treat them as the ultimate arbiter of “right” and “wrong” code. Allow exceptions when logic dictates that bending a stylistic rule leads to clearer, safer, or more maintainable code. Engage the team in deciding which rules matter and which don’t.

Good linting practices might include

Start Small and Iterate: Don’t drop a massive, fully strict configuration onto a legacy codebase. Begin with a small subset of rules that address common bugs or glaring style problems. Ramp up slowly, and give developers time to adapt.

Team Input on Rules: Rather than unilaterally choosing a style guide, get the whole team’s input. Aim for consensus and practicality. Keep the ruleset as minimal as possible.

Context Matters: Allow developers to disable certain rules in special cases. Make it easy to mark exceptions inline with comments and ensure these exceptions are justified.

Focus on Big Wins: Emphasize rules that prevent common errors, improve readability, or catch performance pitfalls. De-prioritize those that are purely aesthetic unless they serve a real purpose.

Regular Reassessment: As the codebase evolves and the team changes, revisit the linting rules. Rules that made sense a year ago might not make sense now.

To Conclude

None of this means we should throw away linters. But it does mean we need to be thoughtful about how we implement them.

In a world where the complexity of systems continues to grow, tools that aid consistency and catch subtle errors can be invaluable—provided we remember their limitations and respect the human element in writing code.

At CodeRabbit, we take a more intelligent approach to code quality by providing AI-powered code review that complements traditional linting tools with contextual suggestions and semantic understanding, moving beyond surface-level formatting to deliver meaningful code improvements.

pill

Still have questions?

Contact us