Skip to content

Fix: Biome Not Working — Rules Not Applied, ESLint Config Not Migrated, or VSCode Extension Ignored

FixDevs ·

Quick Answer

How to fix Biome linter/formatter issues — biome.json configuration, migrating from ESLint and Prettier, VSCode extension setup, CI integration, and rule override syntax.

The Problem

Biome runs but reports no errors on code that should fail:

biome check src/
# Checked 42 file(s) in 23ms
# Found 0 errors.  ← But obvious issues exist

Or ESLint rules migrated to Biome don’t match:

biome migrate eslint --write
# Some rules could not be migrated: no-console, import/order

Or the VSCode extension isn’t formatting on save despite being installed:

// .vscode/settings.json
{
  "editor.formatOnSave": true
}
// Files still format with Prettier instead of Biome

Or Biome and TypeScript disagree on valid code:

// Biome reports: noExplicitAny — but this is intentional
function serialize(value: any): string { ... }

Why This Happens

Biome is a newer tool with different conventions from ESLint + Prettier:

  • Rules are opt-in per group"recommended": true enables recommended rules, but many useful rules require explicit enablement. Without configuring rule groups, most checks are disabled.
  • Biome has fewer rules than ESLint — some ESLint plugins (especially ecosystem-specific ones like eslint-plugin-react-hooks, eslint-plugin-import) don’t have Biome equivalents yet. The migration tool marks these as unsupported.
  • VSCode uses editor.defaultFormatter — to use Biome as the formatter in VSCode, you must set "editor.defaultFormatter": "biomejs.biome" explicitly, not just install the extension.
  • Biome linter and formatter are independent — disabling one doesn’t affect the other. If you only want the formatter (replacing Prettier), configure "linter": { "enabled": false }.

Fix 1: Set Up biome.json Correctly

Biome is configured through biome.json at the project root:

# Initialize Biome in your project
npm install --save-dev --save-exact @biomejs/biome
npx biome init  # Creates biome.json with defaults
// biome.json — complete recommended setup
{
  "$schema": "https://biomejs.dev/schemas/1.9.0/schema.json",
  "vcs": {
    "enabled": true,
    "clientKind": "git",
    "useIgnoreFile": true  // Respect .gitignore for file selection
  },
  "files": {
    "ignoreUnknown": false,
    "ignore": [
      "dist",
      "build",
      ".next",
      "node_modules",
      "coverage",
      "*.min.js",
      "**/__generated__/**"
    ]
  },
  "formatter": {
    "enabled": true,
    "formatWithErrors": false,
    "indentStyle": "space",    // "tab" or "space"
    "indentWidth": 2,
    "lineEnding": "lf",        // "lf", "crlf", "cr"
    "lineWidth": 100,          // Print width (like Prettier's)
    "attributePosition": "auto"  // HTML/JSX attribute wrapping
  },
  "organizeImports": {
    "enabled": true  // Auto-sort imports
  },
  "linter": {
    "enabled": true,
    "rules": {
      "recommended": true,    // Enable all recommended rules
      "correctness": {
        "recommended": true,
        "noUnusedVariables": "error",
        "noUnusedImports": "error"
      },
      "suspicious": {
        "recommended": true,
        "noConsole": "warn"   // Warn on console.log
      },
      "style": {
        "recommended": true,
        "useConst": "error",
        "noVar": "error"
      },
      "performance": {
        "recommended": true
      },
      "security": {
        "recommended": true
      },
      "a11y": {
        "recommended": true   // Accessibility rules
      },
      "complexity": {
        "recommended": true
      }
    }
  },
  "javascript": {
    "formatter": {
      "quoteStyle": "single",          // "single" or "double"
      "jsxQuoteStyle": "double",        // JSX attribute quotes
      "quoteProperties": "asNeeded",    // Only quote object keys when needed
      "trailingCommas": "all",          // "all", "es5", "none"
      "semicolons": "always",           // "always" or "asNeeded"
      "arrowParentheses": "always",     // "(x) => x" vs "x => x"
      "bracketSpacing": true,           // { key: value }
      "bracketSameLine": false          // JSX closing bracket position
    },
    "parser": {
      "unsafeParameterDecoratorsEnabled": true  // For Angular/NestJS decorators
    }
  }
}

Fix 2: Migrate from ESLint and Prettier

# Migrate ESLint config to Biome (reads .eslintrc.* and eslint.config.*)
npx biome migrate eslint --write

# Migrate Prettier config to Biome (reads .prettierrc)
npx biome migrate prettier --write

# After migration, review the generated biome.json
# Check for "inspired" comments — these are approximate equivalents

Manually map common ESLint rules to Biome:

ESLint RuleBiome Equivalent
no-unused-varscorrectness/noUnusedVariables
no-consolesuspicious/noConsole
prefer-conststyle/useConst
no-varstyle/noVar
eqeqeqsuspicious/noDoubleEquals
no-shadowcorrectness/noShadow
react-hooks/rules-of-hookscorrectness/useHookAtTopLevel
react-hooks/exhaustive-depscorrectness/useExhaustiveDependencies
jsx-a11y/alt-texta11y/useAltText

Rules not yet in Biome — keep ESLint for these:

# If you need import/order, no-restricted-imports, or plugin-specific rules,
# run both tools: Biome for formatting + basic linting, ESLint for complex rules
# This is a common transition strategy
// package.json — run both during transition
{
  "scripts": {
    "lint": "biome check . && eslint src --ext .ts,.tsx",
    "format": "biome format --write ."
  }
}

Fix 3: Configure VSCode Extension

// .vscode/settings.json — enable Biome as the default formatter
{
  // Set Biome as default for JS/TS files
  "[javascript]": {
    "editor.defaultFormatter": "biomejs.biome"
  },
  "[javascriptreact]": {
    "editor.defaultFormatter": "biomejs.biome"
  },
  "[typescript]": {
    "editor.defaultFormatter": "biomejs.biome"
  },
  "[typescriptreact]": {
    "editor.defaultFormatter": "biomejs.biome"
  },
  "[json]": {
    "editor.defaultFormatter": "biomejs.biome"
  },
  "[jsonc]": {
    "editor.defaultFormatter": "biomejs.biome"
  },

  // Format and fix on save
  "editor.formatOnSave": true,
  "editor.codeActionsOnSave": {
    "quickfix.biome": "explicit",    // Auto-fix safe issues on save
    "source.organizeImports.biome": "explicit"  // Sort imports on save
  },

  // Disable Prettier and ESLint for files Biome handles
  "prettier.enable": false,
  "eslint.enable": false  // Or keep enabled if running both
}

Verify the extension is using the right Biome binary:

// .vscode/settings.json
{
  // Point to local Biome binary (avoids version mismatches)
  "biome.lspBin": "./node_modules/@biomejs/biome/bin/biome"
}
# Install Biome extension from VSCode marketplace
# Extension ID: biomejs.biome

# Test that Biome works from the CLI
npx biome check --apply src/

Fix 4: Override Specific Rules per File or Directory

Disable rules for specific files or add exceptions:

// biome.json
{
  "linter": {
    "rules": {
      "suspicious": {
        "noExplicitAny": "error"  // Default: error
      }
    }
  },
  "overrides": [
    {
      // Disable rules for test files
      "include": ["**/*.test.ts", "**/*.spec.ts", "**/__tests__/**"],
      "linter": {
        "rules": {
          "suspicious": {
            "noExplicitAny": "off"  // Allow 'any' in tests
          },
          "correctness": {
            "noUnusedVariables": "off"  // Allow unused variables in tests
          }
        }
      }
    },
    {
      // Different formatting for Markdown
      "include": ["**/*.md"],
      "formatter": {
        "lineWidth": 80
      }
    },
    {
      // Generated files — only format, don't lint
      "include": ["src/generated/**"],
      "linter": {
        "enabled": false
      }
    }
  ]
}

Inline suppression (like eslint-disable):

// Suppress a single rule for one line
// biome-ignore lint/suspicious/noExplicitAny: third-party type doesn't provide types
function serialize(value: any): string {
  return JSON.stringify(value);
}

// Suppress the formatter for a block
// biome-ignore format: manually formatted for readability
const matrix = [
  1, 0, 0,
  0, 1, 0,
  0, 0, 1,
];

Fix 5: CI Integration

# GitHub Actions
jobs:
  biome:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: npm

      - run: npm ci

      # Check formatting and lint — fail on any issue
      - run: npx biome ci .
      # Equivalent to: biome check --error-on-warnings .

      # Or use the official GitHub Action
      - uses: biomejs/setup-biome@v2
        with:
          version: latest
      - run: biome ci .
// package.json — useful scripts
{
  "scripts": {
    "check": "biome check .",          // Check without writing
    "check:apply": "biome check --apply .",  // Fix safe issues
    "check:apply-all": "biome check --apply-unsafe .",  // Fix all (may change semantics)
    "format": "biome format --write .",
    "lint": "biome lint .",
    "ci": "biome ci ."                 // CI mode — no writes, exits with error code
  }
}

Pre-commit hook with lint-staged:

// package.json
{
  "lint-staged": {
    "*.{js,jsx,ts,tsx,json}": [
      "biome check --apply --no-errors-on-unmatched"
    ]
  }
}
# Install and configure lint-staged + husky
npm install --save-dev lint-staged husky
npx husky init
echo "npx lint-staged" > .husky/pre-commit

Fix 6: Replace Prettier Completely

If replacing Prettier with Biome as the sole formatter:

# Remove Prettier and related packages
npm uninstall prettier @prettier/plugin-xml prettier-plugin-tailwindcss \
  eslint-config-prettier eslint-plugin-prettier

# Remove Prettier config files
rm .prettierrc .prettierrc.js .prettierignore

# Update .editorconfig to match Biome settings (optional)
// biome.json — Prettier-compatible settings
{
  "formatter": {
    "indentStyle": "space",
    "indentWidth": 2,
    "lineWidth": 80
  },
  "javascript": {
    "formatter": {
      "quoteStyle": "double",       // Prettier default
      "trailingCommas": "all",      // Prettier default (ES5+)
      "semicolons": "always",
      "arrowParentheses": "always"
    }
  }
}

Notable Biome formatting differences from Prettier:

  • Biome adds trailing commas in function parameters (Prettier doesn’t in some cases)
  • Biome handles long import statements differently in some edge cases
  • Biome formats template literals slightly differently for multiline cases
  • JSX formatting is generally compatible

Run biome format --write . then git diff to review all differences from Prettier before committing.

Still Not Working?

Biome ignores files that should be checked — verify biome.json is at the root of the project (same level as package.json). If biome.json is inside a subdirectory, Biome uses it only for that subdirectory. Run biome explain configuration to see which config file Biome is using.

biome check passes but CI fails — ensure the same Biome version is used locally and in CI. Add --exact when installing (npm install --save-dev --save-exact @biomejs/biome) to pin the version. Different Biome versions may have different rule sets.

VSCode extension shows errors that biome check doesn’t — the VSCode extension may be using a different Biome binary (global vs local) or a different config file. Set "biome.lspBin" in .vscode/settings.json to point to the local node_modules/.bin/biome binary.

TypeScript project references not supported — Biome doesn’t read tsconfig.json for type-aware linting (unlike typed ESLint rules like @typescript-eslint/no-floating-promises). Rules requiring type information are not available in Biome. If you rely heavily on typed ESLint rules, keep ESLint for those specific rules alongside Biome for formatting.

For related tooling issues, see Fix: ESLint Config Not Working and Fix: TypeScript Path Alias Not Working.

F

FixDevs

Solo developer based in Japan. Every solution is cross-referenced with official documentation and tested before publishing.

Was this article helpful?

Related Articles