Argument Validation

This content was generated with the assistance of AI and should be verified against the official documentation before being relied on in production.

The reference material consulted while preparing these pages is listed in the section bibliography.

Written against MATLAB R2026b. Function argument validation is built from several features introduced over time; each is dated where it appears: arguments blocks in R2019b, the Name=Value call syntax in R2021a, validation of output arguments in R2022b, mustBeBetween in R2025a (with mustBeInRange not recommended since R2026a), mustBeSorted and metafunction in R2026a, and mustBeScalar and mustBeVectorOrEmpty in R2026b. The release numbers come from the "Since" notes of the R2026b documentation pages and the version notes of the argument-validation pages.

GNU Octave does not support arguments blocks. Every example on this page that uses an arguments block is therefore labelled "not run here" and checked line by line against the R2026b documentation; no output is shown for them, only the documented behaviour. The inputParser, validateattributes and mustBe* examples that Octave 11.3.0 also provides were run, and their output is labelled "Octave 11.3.0 output"; the wording of Octave’s error messages differs from MATLAB’s.

Why declare arguments

A function that can be called by anyone needs to check its inputs, and the classic way is code at the top of the body: nargin tests, isnumeric, isscalar, a loop over varargin looking for names. The documentation describes function argument validation as declarative: the requirements are stated in a block of the function, which removes the checking code and lets the MATLAB desktop tools read the signature by inspection (code completion, hints and the metafunction object below). It also gives optional, repeating and name-value arguments one consistent syntax, with defaults declared next to the argument.

Argument validation is optional. The documentation says it is most useful in functions that can be called from any code, and not needed in local and private functions or in private and protected methods, because the caller already knows the requirements. It is not allowed in nested functions, abstract methods or the destructor of a handle class.

The arguments block

An arguments block starts before the first executable line of the function and ends with end. A function can have several arguments blocks, but all must come before any other code. Each line declares one argument:

argName (dimensions) class {validators} = defaultValue

Every part is optional. Size is the dimensions in parentheses, numbers or colons (a colon allows any length), as in (1,1) for a scalar and (3,:) for three rows; expressions are not allowed there. Class is a single class name. Validators are functions in braces, called from left to right on the value, and the first error stops validation. The default value is any constant or expression that satisfies the declaration, and it makes the argument optional.

function out = myFunction(A, B, C)
    arguments
        A (1,1) string
        B (1,:) double
        C (2,2) cell
    end
    % Function code
end

Not run here (the example of the documentation page): A must be a string scalar, B a row of doubles of any length, C a 2-by-2 cell array.

The four kinds of arguments must be declared in this order: required positional arguments, optional positional arguments, repeating arguments, then name-value arguments. Each is described below.

Class and size conversion

Class and size declarations do not only check: they convert. The documentation lists what happens:

  • a char value is converted to string when the class is string, and a single to double when the class is double; for a class such as an enumeration, a value that can be converted ('full' to a SpeedEnum member) is converted;

  • scalar expansion turns a scalar into an array of the declared size (a 1-by-1 value is compatible with (5,3)), and a column vector is turned into a row when the declared size is (1,:).

So the value inside the function can differ from what the caller passed. Validation functions, in contrast, cannot change the value, and they receive the value after any class and size conversion. To avoid unwanted conversions, leave the class and size out and use validators such as mustBeNumeric and mustBeScalar (the documentation has a section on this). mustBeScalar is new in R2026b; earlier releases have mustBeScalarOrEmpty, which also accepts an empty value.

The order of validation

MATLAB validates the arguments in the order they are declared, top to bottom, and completely validates each one before the next. A default-value expression or a validator can therefore refer to earlier arguments (already validated and converted) but not to later ones. The documentation’s example makes the third argument default to the product of the first two, after the conversion to uint32:

function c = f(a, b, c)
    arguments
        a uint32
        b uint32
        c uint32 = a .* b
    end
    % Function code
end

Not run here, from the documentation: c = f(1.8, 1.5) converts both inputs to uint32 (each becomes 2), so the default is 4; f(1.8, 1.5, 25) returns 25 and does not evaluate the default. A default is validated only when it is used, so an invalid default is an error only for calls that omit the argument. Default expressions are evaluated every time they are used. Validators and defaults must only use the declared arguments: functions that read or change the function workspace (eval, assignin, evalin, exist, feval, nargin, load, save, who, whos and others in the documentation’s list) must not be used in an arguments block. Use no nested functions there, and no argument validation inside the validators themselves.

Required, optional and ignored positional arguments

A positional argument is required unless it has a default value; optional ones must come after all required ones. A default can refer to earlier arguments, as in the documentation’s maxval (1,1) double = max(max(x),max(y)). An optional argument becomes required when a later one is given: to pass minval you must pass maxval. A tilde ~ in the block ignores an input at that position, which cannot have a class, size, validators or a default.

The heatflow scenario has a function that creates a plate. In MATLAB, using an arguments block with a name-value argument for the diffusivity and the boundary kind:

function plate = makePlate(nx, ny, options)
% MAKEPLATE Create a heatflow plate with a zero temperature field.
arguments
    nx (1,1) double {mustBeInteger, mustBePositive}
    ny (1,1) double {mustBeInteger, mustBePositive}
    options.Diffusivity (1,1) double {mustBePositive} = 1.1e-4
    options.Boundary (1,1) string {mustBeMember(options.Boundary, ["Dirichlet" "Neumann" "Periodic"])} = "Dirichlet"
end
plate.nx = nx;
plate.ny = ny;
plate.Diffusivity = options.Diffusivity;
plate.Boundary = options.Boundary;
plate.T = zeros(ny, nx);
end

Not run here (an arguments block; Octave cannot run it). makePlate(4, 3, Boundary="Neumann") and makePlate(4, 3, "Boundary", "Neumann") are both valid after R2021a, and makePlate(0, 3) fails the mustBePositive check of nx.

Name-value arguments

Name-value arguments are always optional, can be passed in any order, and must be declared after all positional and repeating arguments. They are declared as the fields of a structure with dot notation (options.Name), and the structure must appear last in the signature. A default value is optional; if there is none and the caller omits the name, the field does not exist in the structure, which you test with isfield. With no name-value arguments passed, the structure exists and is empty.

function myRectangle(width, height, options)
    arguments
        width double
        height double
        options.LineStyle (1,1) string = "-"
        options.LineWidth (1,1) {mustBeNumeric} = 1
    end
    % Function code
end

Not run here, from the documentation. All of myRectangle(4,5), myRectangle(4,5,LineStyle=":",LineWidth=2) and myRectangle(4,5,LineWidth=2,LineStyle=":") are valid.

  • Names must be unique, also across several structures, and cannot be used by positional arguments. A Repeating block cannot hold name-value arguments, which go in a separate arguments block after it.

  • Partial matching. The names accept a unique abbreviation: with LineWidth and LineStyle, LineW works and Line is an error. The documentation recommends full names.

  • A repeated name is not an error: the last value wins.

  • Validators of one name-value argument cannot refer to another name-value argument, nor can defaults.

  • Text inputs and name-value arguments collide. If a function has optional text arguments and name-value arguments, a call such as mySignal("Mag","coulomb") can be read as the name Mag, matched by abbreviation to Magnifier. The documentation’s remedies are to make the first text argument required or to make all inputs name-value arguments.

  • Properties of a class as names: a function can accept the settable properties of a class as name-value arguments; see the documentation page on name-value arguments from class properties (not run here).

The Name=Value call syntax (R2021a)

Since R2021a a call can write plot(x,y,LineWidth=2) instead of plot(x,y,"LineWidth",2). Functions with an arguments block support both with no extra code. The documentation lists the limits: mix the two only with all name=value arguments last (plot(x,y,"Color","red",LineWidth=2) is valid, plot(x,y,Color="red","LineWidth",2) errors); a positional argument after the name-value ones forces the comma syntax; and a name that is not a valid variable name ("allow-empty") can only be passed with the comma syntax. Declaring the argument in an arguments block guarantees valid names.

Repeating arguments

An arguments (Repeating) block declares positional arguments that can be given any number of times, including zero. If the block declares x and y, every repeat must give both. In the function each argument is a cell array with one element per repeat (1-by-0 when there are none), and the validation is applied to each element. Repeating inputs cannot have defaults, must come after the positional arguments and before name-value arguments, and there is one Repeating input block per function.

function myPlotRepeating(x, y)
    arguments (Repeating)
        x (1,:) double
        y (1,:) double
    end
    z = reshape([x; y], 1, []);
    if ~isempty(z)
        plot(z{:});
    end
end

Not run here, from the documentation: myPlotRepeating(x1,y1,x2,y2) plots two lines. The page advises against varargin together with validation; if legacy code needs it, it must be the only argument of the Repeating block (see Variable Number of Arguments).

Output argument validation (R2022b)

Since R2022b the outputs can be declared too, in a separate block: arguments (Output), which must follow the (Input) block (a block with no type is an input block). Outputs can have size, class and validators, but no defaults and no reference to earlier arguments. It documents the contract and catches a function that returns the wrong shape after a change:

function out = myFunction(A, B, C)
    arguments (Input)
        A (1,1) string
        B (1,:) double
        C (2,2) cell
    end
    arguments (Output)
        out (1,:) double
    end
    % Function code
end

Not run here, from the documentation. A repeating output block (arguments (Output,Repeating)) can contain only one argument.

The mustBe validation functions

The validators are ordinary functions that return nothing and throw an error when the value is not acceptable. MATLAB ships a family; the documentation groups them as follows (each named function calls the listed one on the input, so the same test is available as a plain function):

Group Functions

Numeric value

mustBePositive, mustBeNonpositive, mustBeNonnegative, mustBeNegative, mustBeFinite, mustBeNonNan, mustBeNonzero, mustBeNonsparse, mustBeSparse, mustBeReal, mustBeInteger, mustBeNonmissing

Comparison

mustBeGreaterThan(value,c), mustBeLessThan, mustBeGreaterThanOrEqual, mustBeLessThanOrEqual, mustBeSorted (since R2026a)

Membership and range

mustBeMember(value,S), mustBeBetween(value,lower,upper)

Data type

mustBeA(value,classnames), mustBeNumeric, mustBeNumericOrLogical, mustBeFloat, mustBeUnderlyingType

Size

mustBeNonempty, mustBeScalar (since R2026b), mustBeScalarOrEmpty, mustBeVector, mustBeVectorOrEmpty (since R2026b), mustBeRow, mustBeColumn, mustBeMatrix

Text and files

mustBeFile, mustBeFolder, mustBeFilePathInclusive, mustBeSymbolicLink, mustBeNonzeroLengthText, mustBeText, mustBeTextScalar, mustBeValidVariableName

Range checks. mustBeBetween(A,lower,upper) throws an error if any element lies outside the closed range. It is available since R2025a, takes an optional interval type (the examples use "open" and "closed") and, for tables, DataVariables=. It calls allbetween. It replaces mustBeInRange, which the R2026b documentation marks "not recommended" since R2026a. Code that must also run on R2024b or earlier uses mustBeInRange there.

Size checks. mustBeVectorOrEmpty(value) (R2026b) throws an error unless the value is a row or column vector or empty; the documented example accepts zeros(0,3) and rejects ones(2), and in an arguments block it allows an empty input that a plain mustBeVector would reject. mustBeScalar (R2026b) and mustBeVector require the shape exactly.

function r = weeklyTotals(dailyTotals)
    arguments
        dailyTotals {mustBeVectorOrEmpty}
    end
    if isempty(dailyTotals)
        r = 0;
    else
        r = sum(dailyTotals);
    end
end

Not run here (R2026b feature); this is the documentation’s example of mustBeVectorOrEmpty, and weeklyTotals([]) returns 0 there.

Octave 11.3.0 provides some of the older validators as functions, so the plain calls can be run. Its messages differ from MATLAB’s, and mustBeBetween and mustBeVectorOrEmpty do not exist there:

mustBePositive(3)
try, mustBePositive(-1), catch e, disp(e.message), end
try, mustBeMember(5, [1 2]), catch e, disp(e.message), end
try, mustBeNumeric('a'), catch e, disp(e.message), end

Octave 11.3.0 output (the first call prints nothing):

input must be positive; found 1 elements that were not: values -1
input must be one of the specified valid values; found 1 elements that were not
input must be numeric; found a char

Custom validators

A validator is a function (a local function of the file, or on the path) that follows the documented design: it accepts the value as its first input, depends on nothing else, returns nothing, modifies no state, and throws an error when the check fails. Do not use argument validation inside a validator. The documentation shows mustBeRealUpperTriangular, which uses istriu and isreal and raises an error with its own identifier and message. A validator for the heatflow stability limit dt <= dx^2/(4*alpha) needs two values, so it takes dt first and the others as extra arguments:

function mustBeStable(dt, dx, alpha)
    limit = dx^2 / (4*alpha);
    if ~all(dt <= limit)
        error("heatflow:mustBeStable:unstable", ...
            "Time step must be at most %g (dx^2/(4*alpha)).", limit);
    end
end

Not run here (function file). Used in an arguments block as dt (1,1) double {mustBePositive, mustBeStable(dt, dx, alpha)} it requires dx and alpha to be declared before dt, by the rule of validation order. The identifier follows the component:mnemonic convention; see Errors, Warnings and Exceptions.

The generated error messages

When a validator fails inside an arguments block, MATLAB wraps the validator’s message with the position or name of the argument: the documentation’s mustBeBetween example shows the output

Error using checkBetween (line 3)
 b = checkBetween(x);
               ^
Invalid argument at position 1. Value must be within the range specified by 0 and 5.

(the error is reported against the call line of the caller). A failed class or size conversion, a call with too many arguments or a missing required argument produce their own messages, and a name-value error names the name. The exact wording and the message identifiers vary between releases and are not documented as stable, so test failures with try/catch on err.identifier in your release rather than from this page (not run here). Write validators with messages that say what is wrong and what is required, because that text is what the caller sees.

Legacy alternatives

inputParser (older than arguments) builds a parser object with addRequired, addOptional and addParameter (name-value) and a validation handle for each, then parse and the Results structure. The documentation calls an arguments block the best practice for name-value arguments, because it removes the parsing code from the body and covers both call syntaxes; the inputParser page of the documentation also shows a call with height=10,width=8, so the older tool accepts the Name=Value call syntax too. Octave also has inputParser, so the example below was run (MATLAB code; the exact wording of failures differs):

function plate = makePlate(nx, ny, varargin)
  p = inputParser;
  p.FunctionName = 'makePlate';
  p.addRequired('nx', @(v) isscalar(v) && v == fix(v) && v > 0);
  p.addRequired('ny', @(v) isscalar(v) && v == fix(v) && v > 0);
  p.addParameter('Diffusivity', 1.1e-4, @(v) isscalar(v) && v > 0);
  p.addParameter('Boundary', 'Dirichlet', @(s) any(strcmp(s, {'Dirichlet','Neumann','Periodic'})));
  p.parse(nx, ny, varargin{:});
  plate = p.Results;
  plate.T = zeros(ny, nx);
end

Calling it with makePlate(4, 3, 'Boundary', 'Neumann') and printing pl.Boundary, size(pl.T) and pl.Diffusivity, then with a bad boundary, a bad nx and a name without a value, Octave 11.3.0 printed:

Neumann
   3   4
1.1000e-04
makePlate: failed validation of 'Boundary'.  Checked with "@(s) any (strcmp (s, ({'Dirichlet', 'Neumann', 'Periodic'})))"
makePlate: failed validation of 'nx'.  Checked with "@(v) isscalar (v) && v == fix (v) && v > 0"
makePlate: no value for parameter 'Diffusivity'

MATLAB’s inputParser reports a failure with the identifier MATLAB:InputParser:ArgumentFailedValidation and a message of the form "The value of 'filename' is invalid. It must satisfy the function: ischar." (from the documentation example, not run here). Note the rule of the documentation: when a function takes optional text arguments and name-value pairs, give the optional text arguments validators, or inputParser reads the text as a parameter name.

validateattributes(A, classes, attributes) checks a value inside the function body against class names and attributes such as 'positive', 'scalar' and 'integer'; validatestring matches text against a list of choices. They are still useful where an arguments block is not available (for instance in nested functions) and for checks that depend on several arguments. Octave 11.3.0:

try, validateattributes(-1, {'numeric'}, {'positive'}), catch e, disp(e.message), end
try, validateattributes([1 2], {'numeric'}, {'scalar'}), catch e, disp(e.message), end
validateattributes(5, {'numeric'}, {'scalar','positive','integer'})

Octave 11.3.0 output (the last call is silent when the value is valid):

input must be positive
input must be scalar

The older counting checks narginchk and nargoutchk are on Variable Number of Arguments.

Inspecting signatures with metafunction (R2026a)

obj = metafunction(identifier) returns a matlab.metadata.Function object (or matlab.metadata.Method) that describes a function: its name, description, file and a Signature of type matlab.metadata.CallSignature that exposes the declared arguments. The identifier is the name of a function or constructor, Class/method for a method, or file>localFunction for a local function. Variants take example argument values (Arguments={...}) or types (ArgumentTypes=[...]) and describe the function that MATLAB would call for them. The reference page marks it "Since R2026a" and shows it on a function with an arguments (Input) block. This is the programmatic counterpart of the declarative blocks: a tool can read the contract without calling the function. Not run here (needs a function file on the path):

mf = metafunction("makePlate");
mf.Name
sig = mf.Signature

The properties of CallSignature are documented on its own reference page; check them on your release.

Pitfalls

Pitfall What happens What to do

Class declaration converts silently

x double accepts a single or int8 and converts it; c char accepts a string

Use mustBeNumeric, mustBeFloat or mustBeTextScalar when conversion is unwanted

Size declaration reshapes

(1,:) accepts a column and converts it to a row

Use mustBeRow if the orientation matters

Optional text argument before name-value arguments

f("Mag","coulomb") is read as a partial name

Make the first text argument required, or use name-value arguments only

Default refers to a later argument

The declaration is invalid

Reorder so that defaults use earlier arguments

varargin with an arguments block

Restrictions apply to every value in varargin

Use arguments (Repeating)

Validator calls nargin, eval or exist

Not allowed in an arguments block

Only use declared arguments

arguments in a nested function

Not allowed

Move the check to the parent or use validateattributes

Code written for R2024b or earlier calls mustBeBetween

The function does not exist before R2025a

Use mustBeInRange there, or write the comparison with mustBeGreaterThanOrEqual and mustBeLessThanOrEqual

Octave users

arguments blocks are a syntax error

Use inputParser or validateattributes

Where older books differ

Books and courses from before R2019b check arguments with nargin tests, isnumeric/ischar calls and error, use varargin loops for options, and inputParser for name-value pairs. These still run. Newer code replaces them with arguments blocks and the Name=Value call syntax (R2021a), and nargchk mentioned by older books has been replaced by narginchk and nargoutchk. mustBeInRange is no longer recommended; use mustBeBetween (R2025a).