oxc-project/oxc · warning · OxcDiagnostic

Unexpected function expression.

Error message

Unexpected function expression.

What it means

Diagnostic from the oxlint `prefer-arrow-callback` rule. It fires when a function expression is passed as a callback (e.g. `arr.map(function (x) { ... })`) and an arrow function would work (prefer_arrow_callback.rs:26-30). By default named function expressions and callbacks that reference `this` (allowUnboundThis) are exempt, per the config in the same file.

Source

Thrown at crates/oxc_linter/src/rules/eslint/prefer_arrow_callback.rs:26

    },
};
use oxc_ast_visit::Visit;
use oxc_codegen::{Context, Gen};
use oxc_diagnostics::OxcDiagnostic;
use oxc_ecmascript::{BoundNames, IsSimpleParameterList};
use oxc_macros::declare_oxc_lint;
use oxc_semantic::ScopeFlags;
use oxc_span::{GetSpan, Span};

use crate::{
    AstNode,
    context::LintContext,
    fixer::{RuleFix, RuleFixer},
    rule::{DefaultRuleConfig, Rule},
};

fn prefer_arrow_callback_diagnostic(span: Span) -> OxcDiagnostic {
    OxcDiagnostic::warn("Unexpected function expression.")
        .with_help("Use an arrow function instead.")
        .with_label(span)
}

#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "camelCase", default, deny_unknown_fields)]
struct PreferArrowCallbackConfig {
    /// If this option is set to `true`, named function expressions are allowed.
    allow_named_functions: bool,
    /// If this option is set to `false`, function expressions that reference `this` are reported even when they are not bound to a `this` value.
    allow_unbound_this: bool,
}

impl Default for PreferArrowCallbackConfig {
    fn default() -> Self {
        Self { allow_named_functions: false, allow_unbound_this: true }
    }
}

View on GitHub (pinned to e1e7af627c)

Solutions

  1. Replace the function expression with an arrow function: `function (x) { return x; }` becomes `(x) => x` (auto-fixable where safe).
  2. If the callback relies on its own `this` or `arguments`, keep `function` and add an inline disable, or pass an explicit thisArg and convert.
  3. Tune options: allowNamedFunctions for named helpers, allowUnboundThis (default) to skip this-using callbacks.
  4. Leave the rule on in CI and fix incrementally file by file.

Example fix

// before
const doubled = nums.map(function (n) { return n * 2; });

// after
const doubled = nums.map((n) => n * 2);
Defensive patterns

Strategy: validation

Validate before calling

// .oxlintrc.json — tune exemptions before enabling broadly
{ "rules": { "prefer-arrow-callback": ["warn", { "allowNamedFunctions": false, "allowUnboundThis": true }] } }

Prevention

When it happens

Trigger: Enable `prefer-arrow-callback` and pass an anonymous function expression to any callback position: `setTimeout(function () { ... })`, `[1,2].map(function (n) { return n * 2; })`. Setting allowNamedFunctions=false also flags `map(function double(n) {...})`; allowUnboundThis=false flags callbacks using `this` even unbound.

Common situations: ES5-era code being modernized; callbacks written before the project adopted ES6; teams enabling the option set to catch Vue/jQuery-style `this` usage; interop code where arrow functions change `this` binding and the rule still suggests them (false-positive looking cases with thisArg arguments).

Related errors


AI-assisted analysis of oxc-project/oxc@e1e7af627c (2026-08-20). Data as JSON: /api/errors/4d3b87d56ffb6531. Report an issue: GitHub.