Error Handling and Debugging
error('Id:component', 'message %d', value) stops execution with an identifier and a formatted message.
Concept
error('Id:component', 'message %d', value) stops execution with an identifier and a formatted message. warning(...) prints a message and continues. assert(condition, message) is a compact check.
Branch on err.identifier to recover from expected problems and rethrow the rest. onCleanup(@() ...) guarantees cleanup (closing files, instruments) even when an error occurs.
Breakpoints (click the margin, or dbstop in file at line) dbstop if error Stop where an error happens dbstep, dbcont, dbquit, dbstack
Step, continue, quit, show the call stack Workspace / data tips Inspect variables while paused Pause at a point in code
Code Analyzer (MATLAB editor) / checkcode Static warnings (unused variables, missing semicolons, deprecated functions) lasterr, MException.last The last error
try
risky();
catch err % an MException object
err.identifier, err.message, err.stack
rethrow(err) % or recover
endWhy It Matters
Measurement scripts meet missing files, bad values and disconnected instruments. Robust error handling turns a crash at 2 a.m. into a logged, recoverable event.
Syntax
error('Bench:badChannel', 'Channel %d does not exist', ch);
try ... catch err, fprintf('%s\n', err.message); end
c = onCleanup(@() fclose(fid));Example
20.1 Throwing, catching by identifier, common runtime errors, assert and onCleanup
The helper function that simulates an instrument:
function value = read_sensor(channel)
%READ_SENSOR Returns a simulated reading, or throws a structured error.
if ~ismember(channel, 1:4)
error('Bench:badChannel', 'Channel %d does not exist (valid: 1-4)', channel);
end
if channel == 4
error('Bench:timeout', 'Sensor on channel %d did not answer', channel);
end
value = 12 + channel / 10;
endfor ch = [2 4 7]
try
v = read_sensor(ch);
fprintf('channel %d: %.1f V\n', ch, v)
catch err
switch err.identifier
case 'Bench:timeout'
fprintf('channel %d: timeout -> using last known value (%s)\n', ch, err.message)
otherwise
fprintf('channel %d: error %s: %s\n', ch, err.identifier, err.message)
end
end
end
try
x = [1 2 3];
y = x(5);
catch err
fprintf('indexing error caught: %s\n', err.message)
end
try
A = ones(2, 3); B = ones(2, 3);
C = A * B;
catch err
fprintf('matrix error caught: %s\n', err.message)
end
warning('off', 'all');
w = str2double('abc');
fprintf('str2double(''abc'') = %g (NaN, not an error) -> check with isnan: %d\n', w, isnan(w))
w = str2double('12,5');
fprintf('str2double(''12,5'') = %g (comma read as a thousands separator, not 12.5!)\n', w)
assert(abs(celsius_to_fahrenheit(100) - 212) < 1e-12, 'conversion is wrong')
disp('assert passed')
cleaner = onCleanup(@() disp('onCleanup ran: resources released'));
clear cleanerExpected Result
The timeout was handled as a recoverable case while the invalid channel was reported with its identifier. Indexing past the end and a matrix-dimension mismatch were caught with their messages (MATLAB's wording differs slightly, e.g. "Index exceeds the number of array elements"). str2double returns NaN for text that is not a number rather than throwing, so it must be checked explicitly — and a decimal comma is a trap: '12,5' is read with the comma as a thousands separator and gives 125, not 12.5. onCleanup ran its function when the object was cleared.
channel 2: 12.2 V
channel 4: timeout -> using last known value (Sensor on channel 4 did not answer)
channel 7: error Bench:badChannel: Channel 7 does not exist (valid: 1-4)
indexing error caught: x(5): out of bound 3 (dimensions are 1x3)
matrix error caught: operator *: nonconformant arguments (op1 is 2x3, op2 is 2x3)
str2double('abc') = NaN (NaN, not an error) -> check with isnan: 1
str2double('12,5') = 125 (comma read as a thousands separator, not 12.5!)
assert passed
onCleanup ran: resources releasedCommon Mistakes
Empty catch blocks that hide real errors.
Error messages without identifiers (can't be handled selectively).
Forgetting to close files/instruments when an error occurs.
Debugging by adding disp everywhere instead of using breakpoints.
Best Practices
Use identifiers of the form Component:problem.
Catch only what you can handle; rethrow the rest.
Use dbstop if error while developing.
Validate inputs at function entry.
Interview Relevance
Medium: "how do you handle errors in MATLAB?", "what is an MException?", "how do you debug a script?", "what is onCleanup for?".
Practice Questions
Wrap a fopen in try/catch and report a friendly message if the file is missing.
Write a function that raises an error with an identifier for negative input and test it.
Use dbstop if error on a script that indexes out of bounds and inspect the variables.
Use onCleanup to restore a changed format setting when a function exits.
Quick Quiz
Q1. (Multiple choice) Which object does catch err receive? A) A struct B) An MException C) A string D) A cell Answer: B.
Q2. (Predict the output) For channel 4, what did the example print?
Answer: A timeout message with "using last known value" (verified).
Q3. (Predict the output) str2double('12,5') Answer: 125 — the comma is treated as a thousands separator, not a decimal point (verified). Replace , with . first when parsing European-format numbers: str2double(strrep(s, ',', '.')).
Q4. (Find the bug) try, data = load(file); catch, end — later code fails with "undefined variable data".
Answer: The empty catch hid the load error; handle it (report, default value) or let it propagate.
Coding Challenge
Write a function-free script that tries to convert the texts {'12.6', 'abc', '13.1'} to numbers, raises an error with identifier Parse:bad for invalid text, catches it, and reports which entries were bad while summing the valid ones.
texts = {'12.6', 'abc', '13.1'};
total = 0;
for k = 1:numel(texts)
try
v = str2double(texts{k});
if isnan(v)
error('Parse:bad', 'entry %d ("%s") is not a number', k, texts{k});
end
total = total + v;
catch err
fprintf('%s: %s\n', err.identifier, err.message)
end
end
fprintf('sum of valid entries: %.1f\n', total)