In #1545 the FunctionsFetchException, FunctionsRelayException, and FunctionsHttpException subtypes were added under FunctionException in a non-breaking way (plain inheritance), so existing catch (FunctionException) blocks keep working.
For v3 we should make FunctionException a sealed class so consumers get a compile-checked exhaustive switch over the failure mode:
try {
await supabase.functions.invoke('hello');
} on FunctionException catch (error) {
final message = switch (error) {
FunctionsFetchException() => 'Network failure',
FunctionsRelayException() => 'Relay error',
FunctionsHttpException() => 'Function returned ${error.status}',
};
}
Why this is breaking (hence v3)
sealed implies abstract, so:
- The public
const FunctionException(...) constructor can no longer be used by external code to instantiate a bare FunctionException (e.g. in tests/mocks).
- External packages can no longer extend or implement it.
A non-breaking intermediate sealed base does not help: as long as a bare FunctionException remains constructable, any switch must allow for one, so the three subtypes can never form the closed set the compiler checks for exhaustiveness. Real three-way exhaustiveness requires FunctionException itself to be sealed.
Where
packages/functions_client/lib/src/types.dart
In #1545 the
FunctionsFetchException,FunctionsRelayException, andFunctionsHttpExceptionsubtypes were added underFunctionExceptionin a non-breaking way (plain inheritance), so existingcatch (FunctionException)blocks keep working.For v3 we should make
FunctionExceptionasealedclass so consumers get a compile-checked exhaustiveswitchover the failure mode:Why this is breaking (hence v3)
sealedimpliesabstract, so:const FunctionException(...)constructor can no longer be used by external code to instantiate a bareFunctionException(e.g. in tests/mocks).A non-breaking intermediate sealed base does not help: as long as a bare
FunctionExceptionremains constructable, any switch must allow for one, so the three subtypes can never form the closed set the compiler checks for exhaustiveness. Real three-way exhaustiveness requiresFunctionExceptionitself to besealed.Where
packages/functions_client/lib/src/types.dart