Rules / Suspicious / control-flow-in-finally

control-flow-in-finally

lint/suspicious/control-flow-in-finally
recommended
Same as control_flow_in_finally · Dart lints

Flags return, break, or continue that escapes a finally block.

Control flow leaving a finally overrides whatever the try or catch was doing, including silently discarding an exception that was still propagating — the error simply vanishes — and masking any value the try was about to return. Keep finally blocks limited to cleanup and let exceptions and returns flow through. A break or continue targeting a loop or switch declared inside the finally is fine and left alone, as are closures defined within it; only flow that escapes the finally itself is reported.

Invalid

example.dartdart
int f1() {
  try {
    doThing();
  } finally {
    return 1;
  }
}

void f2() {
  try {
    doThing();
  } finally {
    return;
  }
}

void f3(bool cond) {
  try {
    doThing();
  } finally {
    if (cond) {
      return;
    }
  }
}

void f4() {
  for (var i = 0; i < 10; i++) {
    try {
      doThing();
    } finally {
      break;
    }
  }
}

void f5() {
  for (var i = 0; i < 10; i++) {
    try {
      doThing();
    } finally {
      continue;
    }
  }
}

void f6(bool cond) {
  for (var i = 0; i < 10; i++) {
    try {
      doThing();
    } finally {
      if (cond) break;
    }
  }
}
Avoid control flow (return/break/continue) that escapes a finally block
4 } finally {
5 return 1;
Avoid control flow (return/break/continue) that escapes a finally block
12 } finally {
13 return;
Avoid control flow (return/break/continue) that escapes a finally block
21 if (cond) {
22 return;
Avoid control flow (return/break/continue) that escapes a finally block
31 } finally {
32 break;
Avoid control flow (return/break/continue) that escapes a finally block
41 } finally {
42 continue;
Avoid control flow (return/break/continue) that escapes a finally block
51 } finally {
52 if (cond) break;

Valid

example.dartdart
void g1() {
  try {
    doThing();
  } finally {
    for (var i = 0; i < 10; i++) {
      if (i > 5) break;
    }
  }
}

void g2(int x) {
  try {
    doThing();
  } finally {
    switch (x) {
      case 1:
        break;
      default:
        break;
    }
  }
}

void g3() {
  try {
    doThing();
  } finally {
    final f = () {
      return;
    };
    f();
  }
}

void g4() {
  try {
    doThing();
  } finally {
    doCleanup();
  }
}

int g5() {
  try {
    return 1;
  } finally {
    doCleanup();
  }
}

void g6(bool cond) {
  try {
    doThing();
  } finally {
    while (cond) {
      continue;
    }
  }
}

How to configure

Set the severity of control-flow-in-finally in your falcon.json:

falcon.jsonjson
{
  "linter": {
    "rules": {
      "suspicious": {
        "control-flow-in-finally": "error"
      }
    }
  }
}