> For the complete documentation index, see [llms.txt](https://thescottyjam.gitbook.io/moat-maker/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://thescottyjam.gitbook.io/moat-maker/i-want-to/customize-assertion-error-messages.md).

# Customize Assertion Error Messages

How can I add additional context to an assertion error's message?

Instead of trying to provide facilities to fully customize the error message, Moat Maker strives to simply deliver good and helpful error messages. If you feel a particular error message could be improved in some way, please [submit an issue](https://github.com/theScottyJam/gatekeeper/issues/new) and let us know.

That being said, it's still important to provide ways to add additional context to an error. For this reason, two different parameters have been made available to give you this power: `at` and `errorPrefix`. To show how these behave, let's start with a very simple validator:

```javascript
const hasUsernameValidator = validator`{ name: string }`;
```

If we call `.assertMatches()` without customizing the error at all, we'll be given the following error message:

```javascript
// TypeError: Expected <receivedValue>.name to be of
// type "string" but got type "boolean".
hasUsernameValidator.assertMatches({ name: false });
```

### The "errorPrefix" Assert Parameter

Using `errorPrefix`, we can add arbitrary information to the start of the error string. Note that the `errorPrefix` string provided absolutely must end with a colon.

```javascript
// TypeError: Error in myConfig.json: Expected
// <receivedValue>.name to be of type "string" but
// got type "boolean".
hasUsernameValidator.assertMatches({ name: false }, {
  errorPrefix: 'Error in myConfig.json:',
});
```

### The "at" Assert Parameter

We can also provide a custom `at` field to change the default `<receivedValue>` text to be whatever we want. This serves two purposes. 1. You can use something more helpful than the extremely generic "receivedValue" text. 2. If you're validating a value that's part of a deeper object structure, you can provide information about the path already taken to get to where you are. This example illustrates both of these use cases.

```javascript
const configData = {
  user: { name: false },
};

// TypeError: Expected <myConfig.json>.user.name to be
// of type "string" but got type "boolean".
hasUsernameValidator.assertMatches(configData.user, {
  at: '<myConfig.json>.user',
});
```

### .assertArgs()

For the common scenario of validating user input for your public API, a special `.assertArgs()` function is provided that's pre-configured to provide appropriate "prefix" and "at" fields for you. For the most descriptive errors, it's best to use `.assertArgs()` with a validator that matches against [a tuple with named entries](/moat-maker/resources/syntax-reference.md#tuple-rules), however, any validator can be used.

```typescript
function getName(userInfo: { name: string }) {
  validator`[userInfo: { name: string }]`
    .assertArgs('getName()', arguments);

  return userInfo.name;
}

// TypeError: Received invalid "userInfo" argument for getName():
// Expected <1st argument>.name to be of type "string" but got type "boolean".
getName({ name: false });
```

`.assertArgs()` takes two parameters. The first is the name of the function we're validating the input for. Some examples might be `"getName()"`, `"MyClass.myStaticMethod()"`, `"<date instance>.getDay()"`, or whatever descriptive name you can think of to help someone receiving this error know where the issue happened at. The second argument should be the complete list of arguments your input function takes. You can conveniently use [the arguments object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments) to accomplish this purpose. If you do not wish to use the arguments object, or if you can not (e.g. because you're using an arrow function which does not support it), you can instead choose to use an alternative pattern, like spreading and destructuring:

```typescript
function getName(...allArgs: [userInfo: { name: string }]) {
  const [userInfo] = allArgs;
  validator`[userInfo: { name: string }]`
    .assertArgs('getName()', allArgs);

  return userInfo.name;
}
```

{% hint style="info" %}
**Note:** In the above `getName()` examples, `getName()` must be called with exactly one argument. Conventionally, you're allowed to call a JavaScript function with extra arguments, and JavaScript will silently ignore them. Allowing and ignoring extra arguments can make some JavaScript patterns easier, for example, you can do `arrayOfInfo.map(getName)`, which will auto-call `getName()` with each entry in the array, along with an index and a reference to the array itself. `getName()` will ignore the latter two arguments and only operate on the first. If you wish to allow your end-users to use such patterns, use the rest syntax inside your tuple definition, like this:

```
validator`[userInfo: { name: string }, ...etc: unknown]`
```

Be warned that enabling this pattern can make it harder to make non-breaking updates to your library. If, later, you want to allow your function to accept additional arguments, you might not be able to do so, because your users may already be passing in additional throw-away arguments. For this reason, it is discouraged to ever provide extra arguments to a function. If interested, [here's a discussion](https://es.discourse.group/t/make-readonly-typedarray/712/14) related to this topic, which ends with a JavaScript committee member stating that developers should avoid this practice for this same reason.
{% endhint %}

### What Else Can You Customize?

By default, a TypeError is thrown when an assertion fails. If you need to throw a different error, you can use the `errorFactory` parameter. See the [API reference](https://thescottyjam.gitbook.io/moat-maker/i-want-to/pages/UkOM86xjk8CUC9d5eVxu#validatorinstance.assertmatches) for more details.
