RecommendationFinder is used in several places to produce "Did you mean...?" suggestions when variables or keywords are not found. It performs fuzzy string matching over all candidates, which is O(n×m) per lookup.
Affected locations
robot.variables.notfound.variable_not_found() — iterates over all variable candidates
robot.running.namespace.KeywordRecommendationFinder — iterates over all keywords from all libraries and resources (also affects --dryrun, since KeywordRunner passes recommend_on_failure=True by default)
(A third location in parsing.lexer.settings operates on a small fixed set of setting names, so it is not a performance concern.)
Note that there is already a TODO comment in
|
# TODO: Consider changing the default value of `recommend_on_failure` to False. |
For tools that use Robot Framework's variable resolution programmatically (e.g., IDE language servers, static analysis tools, like RobotCode ), variable_not_found() may be triggered thousands of times during analysis. In large projects with many variables, this becomes a critical bottleneck.
Real-world impact: Analyzing 375 Robot Framework files took over 30 minutes, with the vast majority of time spent in RecommendationFinder. After monkey-patching variable_not_found to skip recommendations, the same analysis completes in under a minute. See: robotcodedev/robotcode#587
The KeywordRecommendationFinder in namespace.py has the same O(n×m) characteristic, though it primarily affects runtime execution and --dryrun rather than static analysis. RobotCode does not use RF's runtime namespace for keyword resolution, so this is not triggered in our case, but other tools or --dryrun with many missing keywords could be affected.
Current workaround
In RobotCode, we now monkey-patch variable_not_found across all modules that import it (robot.variables.notfound, finders, evaluation, store, robot.variables) to replace it with a version that simply raises VariableError without calling RecommendationFinder. This works, but it's fragile — it depends on internal module structure and could break with any refactoring of the robot.variables package.
Suggestion
A simple global flag like RECOMMENDATIONS_ENABLED (e.g., on RecommendationFinder or in robot.utils.recommendations) that can be set to False to skip all fuzzy matching would be sufficient and avoid the need for monkey-patching.
RecommendationFinderis used in several places to produce "Did you mean...?" suggestions when variables or keywords are not found. It performs fuzzy string matching over all candidates, which is O(n×m) per lookup.Affected locations
robot.variables.notfound.variable_not_found()— iterates over all variable candidatesrobot.running.namespace.KeywordRecommendationFinder— iterates over all keywords from all libraries and resources (also affects--dryrun, sinceKeywordRunnerpassesrecommend_on_failure=Trueby default)(A third location in
parsing.lexer.settingsoperates on a small fixed set of setting names, so it is not a performance concern.)Note that there is already a TODO comment in
robotframework/src/robot/running/namespace.py
Line 250 in 1121a9b
For tools that use Robot Framework's variable resolution programmatically (e.g., IDE language servers, static analysis tools, like RobotCode ),
variable_not_found()may be triggered thousands of times during analysis. In large projects with many variables, this becomes a critical bottleneck.Real-world impact: Analyzing 375 Robot Framework files took over 30 minutes, with the vast majority of time spent in
RecommendationFinder. After monkey-patchingvariable_not_foundto skip recommendations, the same analysis completes in under a minute. See: robotcodedev/robotcode#587The
KeywordRecommendationFinderin namespace.py has the same O(n×m) characteristic, though it primarily affects runtime execution and--dryrunrather than static analysis. RobotCode does not use RF's runtime namespace for keyword resolution, so this is not triggered in our case, but other tools or--dryrunwith many missing keywords could be affected.Current workaround
In RobotCode, we now monkey-patch
variable_not_foundacross all modules that import it (robot.variables.notfound,finders,evaluation,store,robot.variables) to replace it with a version that simply raisesVariableErrorwithout callingRecommendationFinder. This works, but it's fragile — it depends on internal module structure and could break with any refactoring of therobot.variablespackage.Suggestion
A simple global flag like
RECOMMENDATIONS_ENABLED(e.g., onRecommendationFinderor inrobot.utils.recommendations) that can be set toFalseto skip all fuzzy matching would be sufficient and avoid the need for monkey-patching.