How to Handle Errors and Use the error_manager Module in Nelson

The error_manager module in Nelson provides a MATLAB-compatible error-handling infrastructure that bridges low-level C++ exceptions with high-level script functions like error, warning, throw, lasterror, and lastwarn.

The nelson-lang/nelson repository implements a robust error-handling system that allows developers to handle errors and use the error_manager module in Nelson scripts through both simple function calls and advanced exception management. This architecture captures stack traces, supports warning states, and enables precise error filtering through the MException class.

Architecture of the error_manager Module

The error_manager module operates across four distinct architectural layers that translate between C++ exceptions and script-level error objects.

The Public C++ API layer, defined in modules/error_manager/src/include/Error.hpp and Error.cpp, provides the Error() and Warning() functions. These capture the current call stack from the Evaluator and throw Nelson::Exception objects. The Exception type layer implements MException in MException.hpp, providing MATLAB-compatible conversion helpers like ArrayOfToException and ExceptionToArrayOf that translate between C++ exceptions and script structs.

The Gateway layer contains builtin implementations such as throwBuiltin.cpp and warningBuiltin.cpp that parse script arguments and invoke the C++ API. This layer also manages warning state machinery through warning('on'), warning('off'), and warning('aserror') commands. Finally, the State storage layer uses the NelsonConfiguration singleton to persist the last warning exception and warning-state maps, enabling lastwarn and lasterror functionality.

Raising Errors and Warnings in Nelson Scripts

Raising a Simple Error

When a script calls error('message'), the builtin gateway in modules/error_manager/builtin/cpp/errorBuiltin.cpp forwards the request to the C++ Error function. This constructs a DebugStack from the current call stack and throws a Nelson::Exception, halting execution immediately.

% Raise a fatal error
error('File not found');

The interpreter catches the C++ exception and displays:


Error: File not found

Configuring Warnings as Errors

The warning function controls emission behavior through three states: on, off, and aserror. In warningBuiltin.cpp, the gateway stores states in NelsonConfiguration. When warning('aserror', 'id') is set, the Warning C++ class checks the state via warningCheckState() and routes to Error() instead of emitting a warning.

% Set warning "my:warn" to behave as an error
warning('on')          % default – enabled
warning('aserror','my:warn');

% This now raises an error instead of a warning
warning('my:warn','Something is odd');

Throwing MException Objects

The throw function re-raises existing MException objects while preserving the original identifier and message. The implementation in throwBuiltin.cpp detects scalar MException structs, uses ArrayOfToException to convert back to a C++ Exception, attaches the current stack trace via DebugStack(eval->callstack,1,trace), and re-throws.

% Create an MException
ME = MException('my:Error','Bad value');
% Re-throw it
throw(ME);

Capturing and Querying Errors

Using Try-Catch Blocks

Nelson supports MATLAB-compatible try-catch syntax. When the interpreter catches a C++ exception, it converts the Exception to an MException struct using ExceptionToArrayOf, making the message, identifier, and stack fields available in the catch clause.

try
    error('Oops');
catch ME
    disp(['Caught: ' ME.message]);   % prints "Caught: Oops"
    disp(['Identifier: ' ME.identifier]); % prints "Identifier: "
end

Retrieving Last Warning and Error States

The lastwarn and lasterror functions query persistent state stored in the NelsonConfiguration singleton. lastwarn retrieves the most recent warning exception, while lasterror accesses the last caught exception from the evaluator.

% Emit a warning
warning('my:warn', 'Something');

% Retrieve it
[wmsg, wid] = lastwarn;  % wmsg = "Something", wid = "my:warn"

% Retrieve last error after catch
try
    error('Bad');
catch
    e = lasterror;
    disp(e.message);   % "Bad"
    disp(e.identifier);% ""
end

Key Implementation Files

The error_manager module spans several critical paths in the nelson-lang/nelson repository:

Summary

  • The error_manager module provides Nelson's complete error-handling infrastructure, bridging low-level C++ exceptions with high-level script functions through the Error and Warning classes.
  • Use error('msg') for fatal errors and warning('msg') for recoverable issues, with warning('aserror','id') to upgrade specific warnings to errors.
  • Capture exceptions using try-catch blocks where the catch variable receives an MException struct containing message, identifier, and stack fields.
  • Query recent errors and warnings via lasterror and lastwarn, which access state stored in the core NelsonConfiguration singleton.

Frequently Asked Questions

How do I convert a warning into a fatal error in Nelson?

Use the warning('aserror', 'identifier') syntax to map a specific warning ID to error behavior. When that warning is subsequently triggered, the Warning C++ class in Warning.cpp checks the state via warningCheckState and routes to the Error function, causing execution to halt immediately rather than continuing with a warning message.

What is the difference between error and throw in Nelson?

The error function creates a new exception with the current call stack and immediately halts execution. The throw function re-raises an existing MException object, preserving its original identifier and message while attaching the current stack trace via DebugStack in throwBuiltin.cpp—useful for re-throwing exceptions in catch blocks without losing the original error context.

How does Nelson store the last warning and error states?

Nelson uses the NelsonConfiguration singleton to persist state across the interpreter session. The lastwarn function retrieves the most recent warning exception from this configuration, while lasterror accesses the last caught exception from the evaluator's state. These functions enable scripts to inspect errors after they occur or outside of immediate try-catch blocks.

Can I customize the identifier when raising an error?

Yes. While the simple error('message') form uses an empty identifier, you can create custom exceptions with specific identifiers using the MException class. Construct the exception with MException('identifier', 'message') and then use throw(ME) to raise it with the custom identifier intact, enabling precise error filtering in catch blocks based on the identifier field.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →