Skip to main content

NIN validation

Checks that a string is a structurally valid Sierra Leone NIN, offline.

import { validateNin } from '@sierrafy/sdk/nin';

const result = validateNin(form.nin);

if (!result.valid) {
return reject(result.error);
}

validateNin(input, options?)​

validateNin(input: unknown, options?: { schema?: NinFormatSchema }): NinValidationResult

It never throws, for any input. Pass it a number, null, an object or a Symbol and you get an invalid result rather than an exception, so you do not need a try block around user input.

The result​

// valid
{
valid: true,
nin: 'ABCD1234',
checks: { length: true, charset: true, checksum: true, blacklist: true }
}

// invalid
{
valid: false,
nin: 'abcd1234',
checks: { length: true, charset: false, checksum: true, blacklist: true },
error: 'INVALID_CHARSET'
}

Every check is reported independently, so you can see everything that is wrong, not just the first problem. valid is true only when all four pass.

nin is the input as validated. For non-string input it is '', so you cannot use it to tell validateNin(12345678) from validateNin(''). It is also caller-controlled text echoed back verbatim, so escape it before putting it in a log line or an HTML page.

Error codes​

When valid is false, error is the first failing check in this order:

OrderCheckError codeFails when
1lengthINVALID_LENGTHLength is not 8, including any non-string input
2charsetINVALID_CHARSETAny character outside A-Z and 0-9, so lowercase, spaces and punctuation all fail
3checksumINVALID_CHECKSUMOnly when a checksum is enabled, which it is not by default
4blacklistBLACKLISTEDThe NIN is in your configured blocklist

There is no normalisation. abcd1234 and ABCD 234 are rejected rather than cleaned up, because silently correcting an identifier hides a bad submission upstream. Trim and uppercase in your own form handling if you want that.

What this is not​

A valid result means the NIN is well formed. It does not mean the NIN exists, is registered, or belongs to the person in front of you. Nothing in Phase 1 contacts NCRA. See Scope.

The format is provisional​

The format was derived from real eID cards, not from NCRA documentation: 8 uppercase alphanumeric characters, no country prefix, no embedded year. The long SL-prefixed number printed on the card is a separate Personal ID Number, which this validator deliberately does not target.

If NCRA confirms something different, you do not have to wait for a release. Configuring the format shows how to override it.

Checksums​

There is no checksum. One of the observed real NINs is all letters and another ends in a letter, so no obvious check digit exists, and NCRA has not confirmed an algorithm.

A Luhn implementation is wired in and disabled. Do not enable it. Luhn runs over the decimal digits extracted from the NIN, so an all-letter NIN has no digits and fails. Enabling it would reject a shape that appears on real cards. It is a placeholder for an algorithm that suits an alphanumeric identifier, if one turns out to exist.