{"record":{"id":"8bc330df1a6f8d9d","repo":"oxc-project/oxc","slug":"unsafe-usage-of-optional-chaining","errorCode":null,"errorMessage":"Unsafe usage of optional chaining","messagePattern":"Unsafe usage of optional chaining","errorType":"validation","errorClass":"OxcDiagnostic","httpStatus":null,"severity":"warning","filePath":"crates/oxc_linter/src/rules/eslint/no_unsafe_optional_chaining.rs","lineNumber":20,"sourceCode":"    AstKind,\n    ast::{AssignmentTarget, match_assignment_target_pattern},\n};\nuse oxc_diagnostics::OxcDiagnostic;\nuse oxc_macros::declare_oxc_lint;\nuse oxc_semantic::NodeId;\nuse oxc_span::Span;\nuse oxc_syntax::operator::LogicalOperator;\nuse schemars::JsonSchema;\nuse serde::Deserialize;\n\nuse crate::{\n    AstNode,\n    context::LintContext,\n    rule::{DefaultRuleConfig, Rule},\n};\n\nfn no_unsafe_optional_chaining_diagnostic(span: Span) -> OxcDiagnostic {\n    OxcDiagnostic::warn(\"Unsafe usage of optional chaining\")\n        .with_help(\"If this short-circuits with 'undefined' the evaluation will throw TypeError\")\n        .with_label(span)\n}\n\nfn no_unsafe_arithmetic_diagnostic(span: Span) -> OxcDiagnostic {\n    OxcDiagnostic::warn(\"Unsafe arithmetic operation on optional chaining\")\n        .with_help(\"This can result in NaN.\")\n        .with_label(span)\n}\n\n#[derive(Debug, Default, Clone, JsonSchema, Deserialize)]\n#[serde(rename_all = \"camelCase\", default, deny_unknown_fields)]\npub struct NoUnsafeOptionalChaining {\n    /// Disallow arithmetic operations on optional chaining expressions.\n    /// If this is true, this rule warns arithmetic operations on optional chaining expressions, which possibly result in NaN.\n    disallow_arithmetic_operators: bool,\n}\n","sourceCodeStart":2,"sourceCodeEnd":38,"githubUrl":"https://github.com/oxc-project/oxc/blob/e1e7af627c8843ab64044ed466b128fcc21a035b/crates/oxc_linter/src/rules/eslint/no_unsafe_optional_chaining.rs#L2-L38","documentation":"Primary diagnostic of oxlint's no-unsafe-optional-chaining rule. An optional chain short-circuits to undefined, and when the chain result flows into a context that requires a non-undefined value (new, calls, tagged templates, destructuring, for-of RHS, with, instanceof, in, spread), the program throws TypeError at runtime.","triggerScenarios":"new (config?.Server)(port); (obj?.handler)(event); 1 in obj?.foo; with (obj?.foo); for (bar of obj?.foo); const { bar } = obj?.foo; bar instanceof obj?.foo.","commonSituations":"Migrating to optional chaining while assuming the value exists; config-driven dynamic constructors; invoking optional event handlers; destructuring API responses that may be missing.","solutions":["Pull the chain into a local and check it before the value-required position.","Replace ?. with plain access where the value is required, so the failure is the intended one.","Provide a default: (obj?.handler ?? defaultHandler)(event).","Guard the chain: if (obj?.handler) { obj.handler(event); }."],"exampleFix":"// before\nconst server = new (config?.Server)(port);\n// after\nconst Server = config?.Server;\nif (Server === undefined) throw new TypeError('config.Server is required');\nconst server = new Server(port);","handlingStrategy":"type-guard","validationCode":"function requireDefined<T>(v: T | undefined, name: string): T {\n  if (v === undefined) throw new TypeError(`${name} is required`);\n  return v;\n}\n// const Server = requireDefined(config?.Server, 'config.Server'); new Server(port);","typeGuard":"const hasHandler = (o: unknown): o is { handler: (e: Event) => void } =>\n  typeof o === 'object' && o !== null && typeof (o as { handler?: unknown }).handler === 'function';","tryCatchPattern":null,"preventionTips":["Never feed an optional chain directly into new, a call, a tagged template, destructuring, for-of, with, in, or instanceof.","Pull chains into named locals and narrow them before value-required positions.","Default handlers with ?? defaultHandler when a fallback exists."],"tags":["eslint","oxlint","optional-chaining","undefined","typeerror"],"backgroundTag":"optional-chaining-typeerror","analyzedSha":"e1e7af627c8843ab64044ed466b128fcc21a035b","analyzedAt":"2026-08-20T07:01:07.079Z","contentChangedAt":"2026-08-20T07:01:07.079Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}