Bug: no-useless-assignment false positive in try-catch block
Environment
Node version: v22.11.0 npm version: v10.9.0 Local ESLint version: v9.17.0 (Currently used) Global ESLint version: Not found Operating System: darwin 24.1.0
What parser are you using?
@typescript-eslint/parser
What did you do?
Configuration
// eslint.config.js
export default [
{
rules: {
"no-useless-assignment": "warn"
},
},
];
async function fn() {
let intermediaryValue;
try {
intermediaryValue = 42;
unsafeFn();
return { error: undefined };
} catch {
return { intermediaryValue };
}
}
function unsafeFn() {
throw new Error();
}
What did you expect to happen?
The intermediaryValue = 42 statement shouldn’t be flagged by the 'no-useless-assignment' rule, as it’s being used in the catch block.
What actually happened?
intermediaryValue = 42 was flagged as ‘not used in subsequent statements’ by mistake.
Link to Minimal Reproducible Example
https://eslint.org/play/#eyJ0ZXh0IjoiLyplc2xpbnQgbm8tdXNlbGVzcy1hc3NpZ25tZW50OiBcIndhcm5cIiAqL1xuXG5hc3luYyBmdW5jdGlvbiBmbigpIHtcbiAgbGV0IGludGVybWVkaWFyeVZhbHVlO1xuICB0cnkge1xuICAgIGludGVybWVkaWFyeVZhbHVlID0gNDI7XG4gICAgdW5zYWZlRm4oKTtcbiAgICByZXR1cm4geyBlcnJvcjogdW5kZWZpbmVkIH07XG4gIH0gY2F0Y2gge1xuICAgIHJldHVybiB7IGludGVybWVkaWFyeVZhbHVlIH07XG4gIH1cbn1cblxuZnVuY3Rpb24gdW5zYWZlRm4oKSB7XG4gIHRocm93IG5ldyBFcnJvcigpO1xufVxuIiwib3B0aW9ucyI6eyJydWxlcyI6e30sImxhbmd1YWdlT3B0aW9ucyI6eyJzb3VyY2VUeXBlIjoibW9kdWxlIiwicGFyc2VyT3B0aW9ucyI6eyJlY21hRmVhdHVyZXMiOnt9fX19fQ==
Participation
- [ ] I am willing to submit a pull request for this issue.
Additional comments
No response
Thanks for the report @kripod. I can reproduce the problem, we'll have to look into this.
Noting that the false positive also occurs with previous versions of ESLint, so this doesn't seem to be a regression related to #19200.
seems a bug to me. and I confirmed that this problem also exists in eslint v9.16.0.
seems like a bug to me also.
let's take some other opinions too, @eslint/eslint-team should we consider this?
I also think this is a bug; marking as accepted. The problem is that when a try block contains a return or break statement, the rule doesn't consider segments in the catch block as possible subsequents of the current segment.
In the above example, the statement return { intermediaryValue } is not considered a subsequent of intermediaryValue = 42, and since there are no other usages of intermediaryValue, the rule flags the assignment as useless.
The code path graph shows no reachable connection from the Literal (42) segment to CatchClause:enter, but that doesn't mean that execution couldn't jump from the try block into the catch block if an error occurs. This is a peculiarity of code path analysis that the rule doesn't currently account for.
I'll take this.
Note: The code path analysis makes some performance tradeoffs when dealing with try-catch statements, as any expression in the try block could potentially branch to the catch block, and creating all of those links would take up a lot of memory.
@Tanujkanti4441 are you still working on this?
@Tanujkanti4441 are you still working on this?
Sorry! didn't get enough time this issue requires, its better to remove the assignment for now in case if anyone want to take this.