oxc-project/oxc · warning
Unexpected `!` in `{name}`.
Error message
Unexpected `!` in `{name}`. What it means
This is oxlint's 'import/no-webpack-loader-syntax' diagnostic. It reports any import or require whose module string contains an exclamation mark, the webpack loader syntax (e.g. import 'babel-loader!./file.js'). Inline loader syntax couples application code to webpack and is ignored or rejected by other bundlers, toolchains, and Node itself, so the rule forbids it.
Source
Thrown at crates/oxc_linter/src/rules/import/no_webpack_loader_syntax.rs:13
use oxc_ast::{
AstKind,
ast::{Argument, Expression},
};
use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
use oxc_semantic::AstNode;
use oxc_span::Span;
use crate::{context::LintContext, rule::Rule};
fn no_named_as_default_diagnostic(name: &str, span: Span) -> OxcDiagnostic {
OxcDiagnostic::warn(format!("Unexpected `!` in `{name}`."))
.with_help("Do not use import syntax to configure webpack loaders")
.with_label(span)
}
#[derive(Debug, Default, Clone)]
pub struct NoWebpackLoaderSyntax;
declare_oxc_lint!(
/// ### What it does
///
/// Forbids using Webpack loader syntax directly in import or require statements.
///
/// ### Why is this bad?
///
/// This loader syntax is non-standard, so it couples the code to Webpack. The recommended way to
/// specify Webpack loader configuration is in a [Webpack configuration file](https://webpack.js.org/concepts/loaders/#configuration).
///
/// ### ExamplesView on GitHub (pinned to e1e7af627c)
Solutions
- Move the loader configuration into the bundler config file (webpack.config.js module.rules, or the equivalent in Vite/esbuild) and import the plain resource: import './app.css'.
- For raw text or assets, use the toolchain's convention (e.g. '?raw' suffix in Vite, asset modules in webpack 5) instead of raw-loader! syntax.
- If the file must stay webpack-only and you accept the coupling, disable the rule for that file with an oxlint-disable comment.
Example fix
// before
import 'raw-loader!./data.txt';
const css = require('style-loader!css-loader!./app.css');
// after (webpack 5 asset modules in webpack.config.js)
import data from './data.txt';
import './app.css'; Defensive patterns
Strategy: validation
Validate before calling
# catch webpack loader syntax before linters or other bundlers do rg -n "(import|require)\s*\(?\s*['\"][^'\"]*![^'\"]*['\"]" src/
Prevention
- Keep all loader configuration in the bundler config file, never in specifiers.
- When copying webpack recipes, strip '!'-chains before committing.
- Test builds with a second toolchain (esbuild/vite) to catch webpack-only syntax early.
When it happens
Trigger: Enable the rule and lint code where an ImportDeclaration source or a require() string literal contains '!', such as 'style-loader!css-loader!./app.css' or 'raw-loader!./data.txt'. The diagnostic names the offending module string in {name}.
Common situations: Projects migrating off webpack to Vite, esbuild, vitest, or Node ESM hit this because those tools do not understand loader chains in the specifier. Copy-pasted older webpack recipes (raw-loader, babel-loader inline, !!style-loader!css-loader!) are the usual sources.
Related errors
- Imported module should be assigned
- Prefer default export on a file with single export.
- Prefer default export to be present on every file that has e
- This module could be mistakenly parsed as script instead of
- Change to `throw new TypeError(...)`
AI-assisted analysis of oxc-project/oxc@e1e7af627c (2026-08-20).
Data as JSON: /api/errors/4b58008a65cba968.
Report an issue: GitHub.