{"record":{"id":"24d1ef4f2aa9d07c","repo":"oxc-project/oxc","slug":"unexpected-sync-method-property-name","errorCode":null,"errorMessage":"Unexpected sync method: '{property_name}'.","messagePattern":"Unexpected sync method: '(.+?)'\\.","errorType":"validation","errorClass":"OxcDiagnostic","httpStatus":null,"severity":"warning","filePath":"crates/oxc_linter/src/rules/node/no_sync.rs","lineNumber":19,"sourceCode":"use rustc_hash::FxHashSet;\nuse schemars::JsonSchema;\nuse serde::Deserialize;\n\nuse oxc_ast::{AstKind, ast::Expression};\nuse oxc_diagnostics::OxcDiagnostic;\nuse oxc_macros::declare_oxc_lint;\nuse oxc_span::Span;\nuse oxc_str::CompactStr;\n\nuse crate::{\n    AstNode,\n    ast_util::get_enclosing_function,\n    context::LintContext,\n    rule::{DefaultRuleConfig, Rule},\n};\n\nfn no_sync_diagnostic(span: Span, property_name: &str) -> OxcDiagnostic {\n    OxcDiagnostic::warn(format!(\"Unexpected sync method: '{property_name}'.\")).with_label(span)\n}\n\n#[derive(Debug, Default, Clone, Deserialize, JsonSchema)]\n#[serde(rename_all = \"camelCase\", default, deny_unknown_fields)]\nstruct NoSyncConfig {\n    /// Whether synchronous methods should be allowed at the top level of a file.\n    allow_at_root_level: bool,\n    /// Function names to ignore.\n    ignores: FxHashSet<CompactStr>,\n}\n\n#[derive(Debug, Default, Clone, Deserialize)]\npub struct NoSync(Box<NoSyncConfig>);\n\ndeclare_oxc_lint!(\n    /// ### What it does\n    ///\n    /// Disallows synchronous methods from being called in Node.js code.","sourceCodeStart":1,"sourceCodeEnd":37,"githubUrl":"https://github.com/oxc-project/oxc/blob/e1e7af627c8843ab64044ed466b128fcc21a035b/crates/oxc_linter/src/rules/node/no_sync.rs#L1-L37","documentation":"Diagnostic from oxlint rule node/no-sync (style). It flags calls to *Sync-suffixed methods (fs.readFileSync, child_process.execSync, ...) inside functions: synchronous IO blocks Node's single-threaded event loop for the whole call, stalling every concurrent request. The message interpolates the exact property name being called. Options: allowAtRootLevel permits sync calls in top-level script code, and ignores allowlists method names.","triggerScenarios":"A member-expression call whose property name ends in 'Sync' — the diagnostic message embeds the property, e.g. \"Unexpected sync method: 'readFileSync'.\" — located inside a function (get_enclosing_function finds a function parent). Not reported when allowAtRootLevel is true and the call sits at file top level, or when the callee matches the ignores set.","commonSituations":"One-off scripts copy-pasted into Express/Fastify handlers where they now stall concurrency; build-tool utilities reused at runtime; migrations from eslint-plugin-n where the ignores allowlist must be re-provided in camelCase JSON; sync JSON requires of big files on the request path.","solutions":["Switch to the async API and await it: 'const d = await fs.promises.readFile(p, \"utf8\")'","Keep sync calls confined to one-shot CLI/bootstrap code and enable { \"allowAtRootLevel\": true } for those directories (or scope the rule to server code only)","Silence deliberate cases via the ignores option with the exact method names: \"node/no-sync\": [\"error\", { \"ignores\": [\"readFileSync\"] }]","Move expensive load-time work (parsing big JSON, requiring heavy modules) into startup, not per-request paths"],"exampleFix":"// before\napp.get('/report', (req, res) => {\n  const data = fs.readFileSync('./data.json', 'utf8'); // blocks the event loop\n  res.send(data);\n});\n\n// after\napp.get('/report', async (req, res) => {\n  const data = await fs.promises.readFile('./data.json', 'utf8');\n  res.send(data);\n});","handlingStrategy":"validation","validationCode":"// .oxlintrc.json — strict for server code\n\"rules\": { \"node/no-sync\": \"error\" }\n// permissive for scripts/\n\"overrides\": [{\n  \"files\": [\"scripts/**\"],\n  \"rules\": { \"node/no-sync\": [\"error\", { \"allowAtRootLevel\": true, \"ignores\": [\"readFileSync\"] }] }\n}]\n\nnpx oxlint -c .oxlintrc.json --deny-warning .","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Default to the promise APIs (fs.promises.*) so the sync variant is never the autocomplete pick","Keep one-shot sync IO in startup or CLI scripts only; request handlers must stay async end to end","Load-test any endpoint that touches the filesystem to surface event-loop stalls the compiler cannot see"],"tags":["node","async","performance","event-loop","oxlint"],"backgroundTag":"blocking-synchronous-io","analyzedSha":"e1e7af627c8843ab64044ed466b128fcc21a035b","analyzedAt":"2026-08-20T07:01:07.079Z","contentChangedAt":"2026-08-20T07:01:07.079Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}