title: Universal and Flexible Error Handling in ECMAScript
icon: IbDocumentText
JavaScript's try-catch
structure is a fundamental tool for error handling, but it can be enhanced for greater flexibility and clarity. This proposal introduces the concept of allowing any block of statements, not just try
blocks, to have associated catch
blocks. Furthermore, each catch block
can have a when
clause to conditionally handle specific errors, providing a more controlled and expressive approach to managing exceptions.
This proposal retains the integrity of JavaScript's control flow while offering developers a more intuitive and streamlined way to handle errors, without introducing unnecessary complexity.
{ /* ...*/ } catch (e) when (true || false) { /* ... */}
This proposal expands JavaScript’s error handling capabilities by allowing any block of statements to have its own catch
block, with the option to conditionally execute those blocks using the when
keyword. This enhancement provides developers with more control, clarity, and flexibility while maintaining compatibility with existing JavaScript syntax.
catch
blocks: Any block of statements, including functions, loops, and even other catch
blocks, can have its own catch
statement.catch
blocks: Since a catch
block is just another block of code, it can also have its own catch
to handle errors within error-handling logic.catch
with when
: The when
clause allows for conditional execution of catch
blocks, improving the readability and control of error handling.catch
block is missing, the error variable is still available in the same scope as the catch
block, allowing for more precise error handling.JavaScript developers often encounter situations where they need to handle errors in specific ways based on the type of error or other conditions. The current try-catch
structure can be limiting in these scenarios, leading to complex nested conditions or multiple try-catch
blocks. By allowing catch
blocks to be attached to any block of statements, developers can handle errors more precisely and maintain a cleaner code structure.
Language as Go and Rust, allow to catch errors inline, but catch
is for control flow, and is important keep this principle. To maintain the control flow, the catch
block in this proposal is optional, and the error variable is available in the same scope as the catch block. With this proposal the following code is possible:
{ var a = 1 } catch (e);
console.log(a);
if (e) console.log(e);
In the previous example you are seeing the combination of an anonymous block
with a catch without a body
. If you want to do the same in actual JavaScript, you will need an additional block and variable:
try { var a = 1 } catch (e) { var err = e; }
console.log(a);
if (e) console.log(err);
when
clause makes the error-handling logic clear and concise.catch
blocks.The proposed syntax allows for catch
blocks to be attached to any code block and for those blocks to conditionally execute based on the when
clause:
/*
any block of statements: try, anonymous, functions,
if, do, catch, finally, ...
*/
{
// Code that may throw an error
// ...
}
catch (e) when (false || true)
{
// Error-handling logic
// ...
// catch is also a block!
}
catch (e) when (false || true)
{
// Error-handling logic
// ...
}
finally
{
// Cleanup code, executed regardless of success or failure
// ... but finally is also a block!
}
catch (e) when (false || true)
{
// Error-handling logic
// ...
}
catch (e);
{/* ... */ } catch when (false || true);
{ /* ... */} catch;
...
The proposed changes to the ECMAScript grammar are as follows:
14.2 Block
Syntax
Block[Yield, Await, Return] :
{ StatementList[?Yield, ?Await, ?Return] opt } Catch[?Yield, ?Await, ?Return]? Finally[?Yield, ?Await, ?Return]?
Catch[Yield, Await, Return] :
catch ( CatchParameter[?Yield, ?Await] ) when ( Expression ) Block[?Yield, ?Await, ?Return]
catch ( CatchParameter[?Yield, ?Await] ) Block[?Yield, ?Await, ?Return]
catch when ( Expression ) Block[?Yield, ?Await, ?Return]
catch Block[?Yield, ?Await, ?Return]
catch ( CatchParameter[?Yield, ?Await] )
catch
Finally[Yield, Await, Return] :
finally Block[?Yield, ?Await, ?Return]
14.15 The try Statement
Syntax
TryStatement[Yield, Await, Return] :
Block[?Yield, ?Await, ?Return]
Block: { StatementList } Catch[?Yield, ?Await, ?Return]? Finally[?Yield, ?Await, ?Return]?
BoundNames
of CatchParameter
contains any duplicate elements.BoundNames
of CatchParameter
also occurs in the LexicallyDeclaredNames
of Block
.BoundNames
of CatchParameter
also occurs in the VarDeclaredNames
of Block
.Expression
in the when
clause is not a valid Boolean expression.Catch: catch ( CatchParameter ) when ( Expression ) Block
oldEnv
be the running execution context's LexicalEnvironment
.catchEnv
be NewDeclarativeEnvironment(oldEnv)
.argName
of the BoundNames
of CatchParameter
, do:
! catchEnv.CreateMutableBinding(argName, false)
.LexicalEnvironment
to catchEnv
.status
be Completion(BindingInitialization)
of CatchParameter
with arguments thrownValue
and catchEnv
.status
is an abrupt completion, then:
LexicalEnvironment
to oldEnv
.? status
.Expression
is false:
B
be Completion(Evaluation)
of Block
.LexicalEnvironment
to oldEnv
.? B
.Catch: catch ( CatchParameter )
oldEnv
be the running execution context's LexicalEnvironment
.catchEnv
be NewDeclarativeEnvironment(oldEnv)
.argName
of the BoundNames
of CatchParameter
, do:
! catchEnv.CreateMutableBinding(argName, false)
.LexicalEnvironment
to catchEnv
.status
be Completion(BindingInitialization)
of CatchParameter
with arguments thrownValue
and catchEnv
.status
is an abrupt completion, then:
LexicalEnvironment
to oldEnv
.? status
.LexicalEnvironment
to oldEnv
.Catch: catch when ( Expression ) Block
oldEnv
be the running execution context's LexicalEnvironment
.CatchParameter
.Expression
:
Expression
is false:
Expression
is true, proceed to the next statement.Catch: catch
oldEnv
be the running execution context's LexicalEnvironment
.CatchParameter
.Block : { StatementList } Catch[?Yield, ?Await, ?Return]? Finally[?Yield, ?Await, ?Return]?
B
be Completion(Evaluation)
of StatementList
.B
is a throw
completion, then:
Catch
is present, evaluate CatchClauseEvaluation
with B.[[Value]]
.CatchClauseEvaluation
returns undefined
, proceed to step 3. C
be the result of CatchClauseEvaluation
.Catch
is present or all Catch
evaluations result in undefined
, rethrow the exception.Finally
is present, evaluate it and:
Finally
evaluation results in an abrupt completion, return that result.? C
or B
, as appropriate.The current try-catch
syntax is limited to the try
block, which can be followed by one or more catch
blocks and an optional finally
block. This structure is restrictive and does not allow for catch
blocks to be attached to other blocks of code.
try
{
// Code that may throw an error
throw new Error("Error in block");
}
catch (error)
{
if (error.message.includes("block")) {
console.log("Caught an error in block:", error.message);
} else {
throw error;
}
}
The proposed syntax allows for catch
blocks to be attached to any block of statements, not just try
blocks. This flexibility enables developers to handle errors more precisely and conditionally, improving the readability and control of error handling.
/* any block of statements */
{
// Code that may throw an error
throw new Error("Error in block");
}
catch (error) /* optional */ when (error.message.includes("block"))
{
console.log("Caught an error in block:", error.message);
}
try-catch
(the current specification)This proposal is compatible with the existing try-catch
syntax.
try
{
// Code that may throw an error
throw new Error("Error in block");
}
catch (error)
{
console.log("Caught an error in block:", error.message);
}
try-catch
with when
clauseUsers can conditionally handle errors based on the when
clause.
try {
data = fetchData();
}
catch (err) when (err instanceof NetworkError) {
console.error('Network error:', err.message);
}
catch (err) when (err instanceof SyntaxError) {
console.error('Syntax error in response:', err.message);
}
finally {
console.log('Cleanup code, executed regardless of success or failure.');
}
anonymous-catch
(no try
block)No try
block is required to have a catch
block.
{
// Code that may throw an error
throw new Error("Error in block");
}
catch (error) when (error.message.includes("block"))
{
console.log("Caught an error in block:", error.message);
}
if-catch
No try
block is required to have a catch
block inside an if
statement.
if (condition) {
// ...
} catch (error) {
console.log("Caught an error in block:", error.message);
} else {
// here we are sure that there is no error in the block
console.log("No error in block.");
}
if-catch
with when
ClauseLike the previous example, but with a when
clause to conditionally handle errors.
if (condition) {
throw new Error("Error in block");
} catch (error) when (error.message.includes("block")) {
console.log("Caught an error in block:", error.message);
}
for-catch
for (let i = 0; i < 3; i++) {
throw new Error("Error in block " + i);
} catch (error) when (error.message.includes("block 1")) {
console.log("Caught an error in block 1:", error.message);
}
while-catch
let i = 0;
while (i < 3) {
throw new Error("Error in block " + i);
} catch (error) when (error.message.includes("block 1")) {
console.log("Caught an error in block 1:", error.message);
i++;
}
function-catch
Functions can have their own catch
blocks.
function fetchData() {
throw new Error("Error in block");
} catch (error) when (error.message.includes("block")) {
console.log("Caught an error in block:", error.message);
}
catch-catch
Nested catch
blocks can handle errors within error-handling logic.
/* ... any block of statements ... */ {
throw new Error("Error in block");
} catch (error) when (error.message.includes("block")) {
console.log("Caught an error in block:", error.message);
} catch (nestedError) {
console.log("Caught a nested error:", nestedError.message);
}
do-catch
Catch exceptions must be before the while
statement.
do {
throw new Error("Error in block");
} catch (error) when (error.message.includes("block")) {
console.log("Caught an error in block:", error.message);
} while (false);
finally-catch
Catch exceptions thrown in the finally
block.
try {
throw new Error("Error in block");
} catch (error) when (error.message.includes("block")) {
console.log("Caught an error in block:", error.message);
} finally {
console.log("Finally block executed.");
throw new Error("Error in finally block");
} catch (nestedError) {
console.log("Caught a nested error:", nestedError.message);
}
try-catch-throw-catch
Catch exceptions thrown in the catch
block.
try {
throw new Error("Error in block");
} catch (error) when (error.message.includes("block")) {
console.log("Caught an error in block:", error.message);
throw new Error("Error in catch block");
} catch (nestedError) {
console.log("Caught a nested error:", nestedError.message);
}
try-cath
with if-catch-when
insideCombine try-catch
with if-catch-when
inside.
try {
// ...
if (condition) {
throw new Error("Error in block");
} catch (error) when (error.message.includes("block")) {
// enter here if error.message.includes("block") is true
// else the exception will be catched by the outer catch block
console.log("Caught an error in if block:", error.message);
}
// ...
} catch (error) {
console.log("Caught an error in try block:", error.message);
}
case-body-catch
Catch exceptions thrown in the case
block.
switch (1) {
case 1: {
throw new Error("Error in block");
} catch (error) when (error.message.includes("block")) {
console.log("Caught an error in block:", error.message);
}
}
// RO = risky operation
// BE = boolean expression
{ /* RO */ } catch;
{ /* RO */ } catch (e);
{ /* RO */ } catch (e) { /* ... */ }
{ /* RO */ } catch (e) { /* ... */ } catch (e) { /* ... */ } /* ... */
{ /* RO */ } catch (e) { /* ... */ } finally { /* ... */} /* ... */
{ /* RO */ } catch when ( /* BE */ );
{ /* RO */ } catch when ( /* BE */ ) { /* ... */} /* ... */
{ /* RO */ } catch when ( /* BE */ ) { /* ... */} finally { /* ... */ } /* ... */
{ /* RO */ } catch (e) when ( /* BE */ );
{ /* RO */ } catch (e) when ( /* BE */ ) { /* ... */ }
{ /* RO */ } catch (e) when ( /* BE */ ) { /* ... */ } catch /* ... */
{ /* RO */ } catch (e) when ( /* BE */ ) { /* ... */ } finally { /* ... */ }
{ /* RO */ } catch (e) when ( /* BE */ ) { /* ... */ } finally { /* ... */ } catch /* ... */
/* ... */
if ( /* BE */ ) { /* RO */ } catch;
if ( /* BE */ ) { /* RO */ } catch (e);
if ( /* BE */ ) { /* RO */ } catch (e) { /* ... */ }
if ( /* BE */ ) { /* RO */ } catch (e) { /* ... */ } catch (e) { /* ... */ } /* ... */
if ( /* BE */ ) { /* RO */ } catch (e) { /* ... */ } finally { /* ... */} /* ... */
if ( /* BE */ ) { /* RO */ } catch when ( /* BE */ );
if ( /* BE */ ) { /* RO */ } catch when ( /* BE */ ) { /* ... */} /* ... */
if ( /* BE */ ) { /* RO */ } catch when ( /* BE */ ) { /* ... */} finally { /* ... */ } /* ... */
if ( /* BE */ ) { /* RO */ } catch (e) when ( /* BE */ );
if ( /* BE */ ) { /* RO */ } catch (e) when ( /* BE */ ) { /* ... */ }
if ( /* BE */ ) { /* RO */ } catch (e) when ( /* BE */ ) { /* ... */ } catch /* ... */
if ( /* BE */ ) { /* RO */ } catch (e) when ( /* BE */ ) { /* ... */ } finally { /* ... */ }
if ( /* BE */ ) { /* RO */ } catch (e) when ( /* BE */ ) { /* ... */ } finally { /* ... */ } catch /* ... */
if ( /* BE */ ) { /* RO */ } else { /* RO */ } catch;
if ( /* BE */ ) { /* RO */ } else { /* RO */ } catch (e);
if ( /* BE */ ) { /* RO */ } else { /* RO */ } catch (e) { /* ... */ }
if ( /* BE */ ) { /* RO */ } else { /* RO */ } catch (e) { /* ... */ } catch (e) { /* ... */ } /* ... */
if ( /* BE */ ) { /* RO */ } else { /* RO */ } catch (e) { /* ... */ } finally { /* ... */} /* ... */
if ( /* BE */ ) { /* RO */ } else { /* RO */ } catch when ( /* BE */ );
/* ... */
for ( /* RO */ ) { /* RO */ } catch;
for ( /* RO */ ) { /* RO */ } catch (e);
for ( /* RO */ ) { /* RO */ } catch (e) { /* ... */ }
for ( /* RO */ ) { /* RO */ } catch (e) { /* ... */ } catch (e) { /* ... */ } /* ... */
for ( /* RO */ ) { /* RO */ } catch (e) { /* ... */ } finally { /* ... */} /* ... */
for ( /* RO */ ) { /* RO */ } catch when ( /* BE */ );
for ( /* RO */ ) { /* RO */ } catch when ( /* BE */ ) { /* ... */} /* ... */
for ( /* RO */ ) { /* RO */ } catch when ( /* BE */ ) { /* ... */} finally { /* ... */ } /* ... */
for ( /* RO */ ) { /* RO */ } catch (e) when ( /* BE */ );
for ( /* RO */ ) { /* RO */ } catch (e) when ( /* BE */ ) { /* ... */ }
for ( /* RO */ ) { /* RO */ } catch (e) when ( /* BE */ ) { /* ... */ } catch /* ... */
for ( /* RO */ ) { /* RO */ } catch (e) when ( /* BE */ ) { /* ... */ } finally { /* ... */ }
for ( /* RO */ ) { /* RO */ } catch (e) when ( /* BE */ ) { /* ... */ } finally { /* ... */ } catch /* ... */
/* ... */
while ( /* BE */ ) { /* RO */ } catch;
while ( /* BE */ ) { /* RO */ } catch (e);
while ( /* BE */ ) { /* RO */ } catch (e) { /* ... */ }
while ( /* BE */ ) { /* RO */ } catch (e) { /* ... */ } catch (e) { /* ... */ } /* ... */
while ( /* BE */ ) { /* RO */ } catch (e) { /* ... */ } finally { /* ... */} /* ... */
while ( /* BE */ ) { /* RO */ } catch when ( /* BE */ );
while ( /* BE */ ) { /* RO */ } catch when ( /* BE */ ) { /* ... */} /* ... */
while ( /* BE */ ) { /* RO */ } catch when ( /* BE */ ) { /* ... */} finally { /* ... */ } /* ... */
while ( /* BE */ ) { /* RO */ } catch (e) when ( /* BE */ );
while ( /* BE */ ) { /* RO */ } catch (e) when ( /* BE */ ) { /* ... */ }
while ( /* BE */ ) { /* RO */ } catch (e) when ( /* BE */ ) { /* ... */ } catch /* ... */
while ( /* BE */ ) { /* RO */ } catch (e) when ( /* BE */ ) { /* ... */ } finally { /* ... */ }
while ( /* BE */ ) { /* RO */ } catch (e) when ( /* BE */ ) { /* ... */ } finally { /* ... */ } catch /* ... */
/* ... */
do { /* RO */ } catch (e) while ( /* BE */ );
do { /* RO */ } catch (e) { /* ... */ } while ( /* BE */ )
do { /* RO */ } catch (e) when ( /* BE */) { /* ... */ } catch (e) { /* ... */ } while ( /* BE */ ) /* ... */
/* ... */
switch ( /* RO */ ) { case 1: { /* RO */ } catch; }
switch ( /* RO */ ) { case 1: { /* RO */ } catch when ( /* BE */ ) { /* ... */}
switch ( /* RO */ ) { case 1: { /* RO */ } catch when ( /* BE */ ) { /* ... */} finally { /* ... */ } }
/* ... */
function f() { /* RO */ } catch;
function f() { /* RO */ } catch (e);
function f() { /* RO */ } catch (e) { /* ... */ }
function f() { /* RO */ } catch (e) { /* ... */ } catch (e) { /* ... */ } /* ... */
function f() { /* RO */ } catch (e) { /* ... */ } finally { /* ... */} /* ... */
function f() { /* RO */ } catch when ( /* BE */ );
function f() { /* RO */ } catch when ( /* BE */ ) { /* ... */} /* ... */
function f() { /* RO */ } catch when ( /* BE */ ) { /* ... */} finally { /* ... */ } /* ... */
function f() { /* RO */ } catch (e) when ( /* BE */ );
function f() { /* RO */ } catch (e) when ( /* BE */ ) { /* ... */ }
function f() { /* RO */ } catch (e) when ( /* BE */ ) { /* ... */ } catch /* ... */
function f() { /* RO */ } catch (e) when ( /* BE */ ) { /* ... */ } finally { /* ... */ }
function f() { /* RO */ } catch (e) when ( /* BE */ ) { /* ... */ } finally { /* ... */ } catch /* ... */
/* ... */
In JavaScript, when an exception is thrown, it is caught by the first catch block found in the hierarchy. This behavior remains consistent with the proposed changes. If a block does not catch the exception (either because it lacks a catch block or because the when condition evaluates to false), the exception will propagate up the call stack, where it can be caught by a higher-level catch block.
This ensures that the traditional flow of exception handling is preserved. The flexibility introduced by allowing any block to have a catch block (and potentially a when
condition) simply extends this existing mechanism, giving developers more control over how and where exceptions are handled, without altering the fundamental principles of exception propagation.
{}
While some proposals seek to move away from the traditional try-catch
structure, often resorting to if
statements or introducing new operators, this proposal embraces and expands upon the existing use of braces {}
to maintain consistency with the current JavaScript syntax and control flow structures.
Braces {}
are a fundamental part of JavaScript's syntax, serving as the primary means to define code blocks. By leveraging this familiar structure, the proposal ensures that developers can manage errors within the same framework they use for other control flows like if
, for
, and while
loops.
Semi-colons ;
are also a fundamental part of JavaScript's syntax, serving as the primary means to separate statements. In this proposal, is recommended to use semi-colons to separate statements, but is not mandatory. For example:
{ throw new Error("Error in block") } catch
(1 + 1)
The previous code is valid, but is recommended to use semi-colons to separate statements, because the interpreter doesn't know if ( 1 + 1)
is part of the catch
block or not. Then, the following code is recommended:
{ throw new Error("Error in block") } catch; // <-- semicolon
(1 + 1)
At its core, error handling is about controlling the flow of execution in the presence of unexpected conditions. By expanding the capabilities of blocks with optional catch
and finally
clauses, this proposal provides a powerful yet intuitive way to manage errors without introducing new or unfamiliar syntax. The focus remains on enhancing existing structures, ensuring that the language remains coherent and that the learning curve for developers is minimal.
Moving away from try-catch
often results in the use of if
statements or other control structures that, while functional, can lead to redundant or less expressive code. This proposal addresses error handling in a more integrated manner, allowing developers to manage exceptions within the same block structure that controls their program's logic.
Error handling is inherently about structuring your code to handle the unexpected. This proposal keeps the focus on structure by using control flow blocks, rather than introducing operators or new constructs that might disrupt the logical flow of code. By sticking with braces, we ensure that error handling remains a natural extension of the language's existing syntax and philosophy.
Storing a value in memory is not the same as telling the interpreter what the next block of statements to execute is.
This proposal advocates for an evolution of JavaScript's error-handling capabilities that respects and enhances the language's foundational structures, ensuring that developers can write cleaner, more maintainable code without sacrificing familiarity or simplicity.
Currently, JavaScript lacks the ability to type or conditionally handle errors directly in catch
blocks, resulting in complex and less readable code. This proposal introduces a more precise and clear way to handle errors, inspired by similar features in languages such as C#, F#, Scala, PL/pgSQL, Ruby, BASIC, Go, and Rust, as well as real-world scenarios where more granular error handling is needed.
C# and F# when
Clause: Both C# and F# provide a when
clause in their catch
blocks, allowing developers to handle exceptions based on specific conditions. This inspired the idea of bringing a similar conditional mechanism to JavaScript.
try
{
// Code that may throw an error
}
catch (Exception ex) when (ex.Message.Contains("block"))
{
Console.WriteLine("Caught an error in block: " + ex.Message);
}
Scala's Pattern Matching in catch
: Scala's ability to use pattern matching within catch
blocks, combined with conditional logic, influenced the design of conditional catch
blocks with when
in this proposal.
try {
// Code that may throw an error
} catch {
case ex: Exception if ex.getMessage.contains("block") =>
println(s"Caught an error in block: ${ex.getMessage}")
}
PL/pgSQL's EXCEPTION
Handling: In PL/pgSQL, the EXCEPTION section within functions allows for specific error handling based on the type of exception, providing a structured approach to managing errors in procedural code. This inspired the idea of enhancing JavaScript's error handling within blocks and functions.
BEGIN
-- Code that may throw an error
EXCEPTION
WHEN OTHERS THEN
-- Error-handling logic
END;
BASIC's On Error
Statement: The On Error
mechanism in BASIC languages like Visual Basic offers a way to direct the flow of control when an error occurs, similar to the concept of catch blocks. This inspired the proposal to allow more flexible and conditional error handling in JavaScript.
On Error Goto ErrorHandler
' Code that may throw an error
Exit Sub
ErrorHandler:
' Error-handling logic
Ruby's rescue
with Conditions: Ruby's elegant error-handling using rescue
, which can include conditional logic within the block, inspired the flexibility and readability goals of this proposal.
begin
# Code that may throw an error
rescue => e
puts "Caught an error: #{e.message}" if e.message.include?("block")
end
Go an Rust: Go and Rust allow to catch errors inline, but catch
is for control flow, and is important keep this principle. To maintain the control flow, the catch
block in this proposal is optional, and the error variable is available in the same scope as the catch block.
// Go
if num, err := strconv.Atoi("123a"); err != nil {
fmt.Println("Error:", err)
} else {
fmt.Println("Number:", num)
}
// Rust
let num = "123a".parse::<i32>();
if let Err(e) = num {
println!("Error: {}", e);
} else {
println!("Number: {}", num.unwrap());
}
Real-World Scenarios: The need for more granular control over error handling in complex JavaScript applications highlighted the limitations of the current try-catch
structure and motivated the development of this more flexible approach.
By synthesizing these ideas and experiences from various languages and systems, this proposal aims to provide a more powerful and flexible approach to error handling in JavaScript, while maintaining the simplicity and dynamism that the language is known for.
Crockford, Douglas. JavaScript: The Good Parts. O'Reilly Media, 2008. ISBN: 978-0596517748.
Simpson, Kyle. You Don't Know JS: Scope & Closures. O'Reilly Media, 2014. ISBN: 978-1449335588.
Hunt, Andrew, and David Thomas. The Pragmatic Programmer: Your Journey to Mastery. Addison-Wesley Professional, 1999. ISBN: 978-0201616224.
Scott, Michael L. Programming Language Pragmatics. Morgan Kaufmann, 2009. ISBN: 978-0123745149.
McConnell, Steve. Code Complete: A Practical Handbook of Software Construction. Microsoft Press, 2004. ISBN: 978-0735619678.
Flanagan, David. JavaScript: The Definitive Guide. O'Reilly Media, 2020. ISBN: 978-1491952023.
W3Schools. "JavaScript Errors - Throw and Try to Catch". https://www.w3schools.com/js/js_errors.asp
Mozilla Developer Network. "Error". https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error
Microsoft Docs. "try-catch (C# Reference)". https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/try-catch
Scala Documentation. "Functional Error Handling". https://docs.scala-lang.org/scala3/book/fp-functional-error-handling.html
PostgreSQL Documentation. "PL/pgSQL - Error Handling". https://www.postgresql.org/docs/13/plpgsql-control-structures.html#PLPGSQL-ERROR-TRAPPING
Ruby Documentation. "Exceptions". https://ruby-doc.org/core-3.0.2/doc/syntax/exceptions_rdoc.html
BASIC Programming Language. "On Error Statement". https://docs.microsoft.com/en-us/office/vba/language/reference/user-interface-help/on-error-statement
The Go Programming Language. "Error Handling". https://golang.org/doc/effective_go#errors
The Rust Programming Language. "Error Handling". https://doc.rust-lang.org/book/ch09-00-error-handling.html
JavaScript Standard ECMA-262. https://tc39.es/ecma262
Rafael Rodríguez Ramírez
rafageist@divengine.com
rafageist.com
This proposal is licensed under the MIT License.