oxc-project/oxc · warning
File has too many classes ({total}). Maximum allowed is {max
Error message
File has too many classes ({total}). Maximum allowed is {max} What it means
Diagnostic of the `max-classes-per-file` rule. It counts class declarations (and by default class expressions too) in a single file and reports when the count exceeds the configured maximum, with default `max: 1` (crates/oxc_linter/src/rules/eslint/max_classes_per_file.rs:38-41). The span labels the class that pushed the file over the limit. The intent is one-responsibility-per-file cohesion.
Source
Thrown at crates/oxc_linter/src/rules/eslint/max_classes_per_file.rs:13
use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
use oxc_span::{GetSpan, Span};
use schemars::JsonSchema;
use serde::Deserialize;
use crate::{
context::LintContext,
rule::{DefaultRuleConfig, Rule},
};
fn max_classes_per_file_diagnostic(total: u32, max: u32, span: Span) -> OxcDiagnostic {
OxcDiagnostic::warn(format!("File has too many classes ({total}). Maximum allowed is {max}"))
.with_help("Reduce the number of classes in this file")
.with_label(span)
}
#[derive(Debug, Default, Clone, Deserialize)]
pub struct MaxClassesPerFile(Box<MaxClassesPerFileConfig>);
#[derive(Debug, Clone, JsonSchema, Deserialize)]
#[serde(rename_all = "camelCase", default, deny_unknown_fields)]
pub struct MaxClassesPerFileConfig {
/// The maximum number of classes allowed per file.
pub max: u32,
/// Whether to ignore class expressions when counting classes.
pub ignore_expressions: bool,
}
impl std::ops::Deref for MaxClassesPerFile {
type Target = MaxClassesPerFileConfig;View on GitHub (pinned to e1e7af627c)
Solutions
- Split the file so each class lives in its own module (matches the rule's intent and default max of 1).
- If multiple related classes legitimately belong together (e.g. AST node types, DTOs), raise the limit: `{ "max": 5 }`.
- Set `ignoreExpressions: true` when class expressions are used for anonymous/one-off implementations such as HOCs or dynamic classes.
Example fix
// before (file: shapes.js)
class Circle { /* ... */ }
class Square { /* ... */ }
// after: shapes/circle.js -> export class Circle {...}
// shapes/square.js -> export class Square {...} Defensive patterns
Strategy: validation
Validate before calling
// CI gate before merge:
// oxlint --rule max-classes-per-file='{"max":1}' src/
// For mixed modules: {"max": 3, "ignoreExpressions": true} Prevention
- Default to one class per file when scaffolding; new files are cheap, splits later are not.
- Use class expressions for anonymous one-offs if the team counts declarations only (ignoreExpressions).
- Watch test files that inline mock classes — configure per-glob overrides instead of weakening the global limit.
When it happens
Trigger: A file containing two or more classes with default config: `class A {} class B {}` triggers immediately. Any `class ... {}` declaration increments the counter; class expressions (`const A = class {}`) also count unless `ignoreExpressions: true` is set. Config `{ "max-classes-per-file": ["error", { "max": 3, "ignoreExpressions": true }] }` changes the thresholds.
Common situations: Bundling helper/mock classes or test doubles into one test file; exporting multiple small value-object classes from a barrel-ish module; migrating from ESLint where the rule was enabled with default max 1; refactoring that temporarily introduces an extra class during extraction.
Related errors
- Expected method{method_name_str} to have this.
- {prefix} {{ after '{keyword}'{condition_if_needed}.
- Enforce default clauses in switch statements to be last
- Expected a function {style}.
- Accessor pair {getter_key} and {setter_key} should be groupe
AI-assisted analysis of oxc-project/oxc@e1e7af627c (2026-08-20).
Data as JSON: /api/errors/1ee842307af10910.
Report an issue: GitHub.