use-rethrow-when-possible

Same as use_rethrow_when_possible in Dart lints

Path
lint/suspicious/use-rethrow-when-possible
Default
On (recommended)
Origin
Dart lints
Rule
501 of 512
recommended

Flags throw e inside a catch (e) by matching the exception parameter's name.

Re-throwing the caught object with throw e starts a fresh stack trace from the catch site, discarding the original point of failure and making the error far harder to trace. Use rethrow, which propagates the same exception with its trace intact. Matching is syntactic: the thrown identifier must have the exception parameter's spelling; binding identity is not resolved. Throws inside a nested closure or a nested try/catch are skipped.

Invalid

example.dartdart
// Bad: re-throwing the caught exception with `throw e` instead of `rethrow`.
bool cond = true;
void x() {}
void log(Object o) {}

void a() {
  try {
    x();
  } catch (e) {
    throw e;
  }
}

void b() {
  try {
    x();
  } catch (e) {
    log(e);
    throw e;
  }
}

void c() {
  try {
    x();
  } catch (e) {
    if (cond) {
      throw e;
    }
  }
}

void d() {
  try {
    x();
  } on Exception catch (e) {
    throw e;
  }
}

void e2() {
  try {
    x();
  } catch (err, st) {
    log(st);
    throw err;
  }
}

void nestedCatchInsideFunctionBoundaries() {
  try {
    x();
  } catch (outer) {
    final callback = () {
      try {
        x();
      } catch (inner) {
        throw inner;
      }
    };
    void local() {
      try {
        x();
      } catch (inner) {
        throw inner;
      }
    }
    callback();
    local();
    throw outer;
  }
}
Use `rethrow` to re-throw the caught exception and preserve its stack trace.
9 } catch (e) {
10 throw e;
Use `rethrow` to re-throw the caught exception and preserve its stack trace.
18 log(e);
19 throw e;
Use `rethrow` to re-throw the caught exception and preserve its stack trace.
27 if (cond) {
28 throw e;
Use `rethrow` to re-throw the caught exception and preserve its stack trace.
36 } on Exception catch (e) {
37 throw e;
Use `rethrow` to re-throw the caught exception and preserve its stack trace.
45 log(st);
46 throw err;
Use `rethrow` to re-throw the caught exception and preserve its stack trace.
57 } catch (inner) {
58 throw inner;
Use `rethrow` to re-throw the caught exception and preserve its stack trace.
64 } catch (inner) {
65 throw inner;
Use `rethrow` to re-throw the caught exception and preserve its stack trace.
69 local();
70 throw outer;

Valid

example.dartdart
// Good: `rethrow`, or a throw that is not equivalent to rethrowing the caught exception.
void x() {}
void y() {}
void log(Object o) {}

void a() {
  try {
    x();
  } catch (e) {
    rethrow; // already uses rethrow
  }
}

void b() {
  try {
    x();
  } catch (e) {
    throw StateError('nope'); // throws a different object
  }
}

void c() {
  try {
    x();
  } catch (e) {
    throw Exception(e); // wraps e rather than rethrowing it
  }
}

void d() {
  try {
    x();
  } catch (e) {
    void handler() {
      throw e; // inside a nested function: rethrow would be illegal here
    }

    handler();
  }
}

void e2() {
  try {
    x();
  } catch (e) {
    try {
      y();
    } catch (e2) {
      throw e; // refers to the outer exception; rethrow is not valid here
    }
  }
}

void f() {
  try {
    x();
  } catch (e) {
    final cb = () {
      throw e; // inside a closure expression
    };
    cb();
  }
}

void nestedTryDoesNotRethrowOuterBinding() {
  try {
    x();
  } catch (outer) {
    try {
      throw outer;
    } catch (inner) {
      throw outer;
    } finally {
      throw outer;
    }
  }
}

Configure use-rethrow-when-possible

Set its severity in falcon.json. See the configuration guide.

falcon.jsonjson
{
  "linter": {
    "rules": {
      "suspicious": {
        "use-rethrow-when-possible": "error"
      }
    }
  }
}

Or silence one occurrence with a suppression comment; the reason is required.

example.dartdart
// falcon-ignore lint/suspicious/use-rethrow-when-possible: <reason>