{"id":"3d058c16cd4030de","repo":"eslint/eslint","slug":"sourcecode-methodname-cannot-be-called-insi","errorCode":null,"errorMessage":"`SourceCode#${methodName}()` cannot be called inside a rule.","messagePattern":"`SourceCode#(.+?)\\(\\)` cannot be called inside a rule\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"lib/rule-tester/rule-tester.js","lineNumber":323,"sourceCode":" * @param {string} methodName The name of the method to forbid.\n * @param {Function} prototype The prototype with the original method to call.\n * @returns {Function} The function that throws the error.\n */\nfunction throwForbiddenMethodError(methodName, prototype) {\n\tconst original = prototype[methodName];\n\n\treturn function (...args) {\n\t\tconst called = forbiddenMethodCalls.get(methodName);\n\n\t\t/* eslint-disable no-invalid-this -- needed to operate as a method. */\n\t\tif (!called.has(this)) {\n\t\t\tcalled.add(this);\n\n\t\t\treturn original.apply(this, args);\n\t\t}\n\t\t/* eslint-enable no-invalid-this -- not needed past this point */\n\n\t\tthrow new Error(\n\t\t\t`\\`SourceCode#${methodName}()\\` cannot be called inside a rule.`,\n\t\t);\n\t};\n}\n\n/**\n * Extracts names of {{ placeholders }} from the reported message.\n * @param   {string} message Reported message\n * @returns {string[]} Array of placeholder names\n */\nfunction getMessagePlaceholders(message) {\n\tconst matcher = getPlaceholderMatcher();\n\n\treturn Array.from(message.matchAll(matcher), ([, name]) => name.trim());\n}\n\n/**\n * Returns the placeholders in the reported messages but","sourceCodeStart":305,"sourceCodeEnd":341,"githubUrl":"https://github.com/eslint/eslint/blob/f131c034ad91bbf06bcbb6b5e931447a8e419a46/lib/rule-tester/rule-tester.js#L305-L341","documentation":"Thrown by throwForbiddenMethodError() at lib/rule-tester/rule-tester.js:323 for the methods in forbiddenMethods: applyInlineConfig, applyLanguageOptions, finalize. RuleTester monkeypatches SourceCode.prototype so each of these methods can be called at most once per SourceCode instance — the first call (the legitimate one by the linter's config-apply pipeline) is allowed through, any subsequent call (i.e. a rule calling it) throws.","triggerScenarios":"Inside a rule's `create()` handler, the rule explicitly calls `context.sourceCode.applyInlineConfig()`, `.applyLanguageOptions()`, or `.finalize()`, causing a second invocation of that method on the same SourceCode instance during a test. These methods are part of the linter's lifecycle and are not meant to be invoked by rule code.","commonSituations":"A rule author mistakenly thinks they need to apply inline config or finalize the source code themselves; copy-paste from the core Linter pipeline into a rule; a rule that mutates SourceCode state expecting re-initialization.","solutions":["Remove the call to applyInlineConfig / applyLanguageOptions / finalize from the rule body — these are the linter's responsibility.","If the rule needs language options, read them from `context.languageOptions` instead of forcing application.","If the rule needs inline config effects, that indicates a design issue; restructure so the rule reads already-applied state."],"exampleFix":"// before\ncreate(context) {\n  context.sourceCode.applyInlineConfig();\n  return { Program(node) { /* ... */ } };\n}\n\n// after\ncreate(context) {\n  return { Program(node) { /* ... */ } };\n}","handlingStrategy":"validation","validationCode":"const FORBIDDEN = new Set([\"applyInlineConfig\",\"applyLanguageOptions\",\"finalize\"]);\nconst ruleSrc = require('node:fs').readFileSync(rulePath,'utf8');\nfor (const m of FORBIDDEN) {\n  if (ruleSrc.includes(`sourceCode.${m}`) || ruleSrc.includes(`.sourceCode.${m}`)) {\n    throw new Error(`Rule must not call SourceCode#${m}()`);\n  }\n}","typeGuard":"/** @param {string} method */\nfunction isForbiddenSourceCodeMethod(method) {\n  return [\"applyInlineConfig\",\"applyLanguageOptions\",\"finalize\"].includes(method);\n}","tryCatchPattern":null,"preventionTips":["Treat applyInlineConfig/applyLanguageOptions/finalize as linter-internal; never call them from rules.","Read language settings from `context.languageOptions` instead of forcing application.","If you think you need these methods, you are likely re-implementing the linter's pipeline."],"tags":["rule-tester","source-code","lifecycle","custom-rules"],"analyzedSha":"f131c034ad91bbf06bcbb6b5e931447a8e419a46","analyzedAt":"2026-08-03T19:53:24.025Z","schemaVersion":2}