denoland/deno · error · TypeError
ERR_INVALID_ARG_VALUE
ERR_INVALID_ARG_VALUE
Error message
The property 'options.${key}' is invalid. Received ${value} What it means
getUIntOption() reads numeric constructor options such as authTagLength and requires value >>> 0 === value, i.e. a valid uint32. Negative numbers, fractional numbers, NaN, values above 4294967295, and non-number types all fail the check and throw ERR_INVALID_ARG_VALUE on 'options.<key>' (e.g. options.authTagLength). Used by both Cipheriv and Decipheriv option handling.
Source
Thrown at ext/node/polyfills/internal/crypto/cipher.ts:489
}
set lastChunkIsNonZero(value: boolean) {
this.#lastChunkIsNonZero = value;
}
}
function getBlockSize(cipher: string): number {
if (StringPrototypeStartsWith(cipher, "des")) {
return 8;
}
return 16;
}
function getUIntOption(options, key) {
let value;
if (options && (value = options[key]) != null) {
if (value >>> 0 !== value) {
throw new ERR_INVALID_ARG_VALUE(`options.${key}`, value);
}
return value;
}
return -1;
}
function Decipheriv(
cipher: string,
key: any,
iv: any,
options?: any,
) {
if (!ObjectPrototypeIsPrototypeOf(Decipheriv.prototype, this)) {
return new Decipheriv(cipher, key, iv, options);
}
const authTagLength = getUIntOption(options, "authTagLength");
View on GitHub (pinned to 9ad36f7a2c)
Solutions
- Pass a non-negative integer between 0 and 4294967295, e.g. authTagLength: 16.
- Sanitize before the call: Number.isInteger(x) && x >= 0 && x <= 0xFFFFFFFF.
- Type the options object (authTagLength?: number) so strings are caught at compile time.
Example fix
// before
const d = crypto.createDecipheriv('aes-128-gcm', key, iv, { authTagLength: cfg.tagLen }); // cfg.tagLen = "16"
// after
const tagLen = Number(cfg.tagLen);
if (!Number.isInteger(tagLen) || tagLen < 0) throw new Error('bad tagLen');
const d = crypto.createDecipheriv('aes-128-gcm', key, iv, { authTagLength: tagLen }); Defensive patterns
Strategy: validation
Validate before calling
function validateUIntOption(value: unknown, name: string): number {
const n = typeof value === 'string' ? Number(value) : value;
if (typeof n !== 'number' || !Number.isInteger(n) || n < 0 || n > 0xFFFFFFFF)
throw new TypeError(`options.${name} must be a uint32, got ${String(value)}`);
return n;
}
const opts = { authTagLength: validateUIntOption(cfg.authTagLength, 'authTagLength') }; Type guard
function isUInt32(v: unknown): v is number {
return typeof v === 'number' && Number.isInteger(v) && v >= 0 && v <= 0xFFFFFFFF;
} Prevention
- Convert config strings to numbers before putting them in crypto options.
- Declare option types as `number` in TS interfaces to catch string literals.
- Never compute authTagLength with arithmetic that can produce negatives or fractions.
When it happens
Trigger: createDecipheriv('aes-128-gcm', key, iv, { authTagLength: -1 }); { authTagLength: 4.5 }; { authTagLength: '16' } (string from config/JSON); authTagLength parsed from a protocol header without numeric conversion.
Common situations: Options loaded from JSON/YAML where numbers arrive as strings; tag lengths computed from arithmetic that can go negative or fractional; environment variables passed straight into options.
Related errors
- ERR_INVALID_ARG_TYPE
- ERR_INVALID_ARG_TYPE
- ERR_CRYPTO_UNKNOWN_CIPHER
- ERR_CRYPTO_INVALID_STATE
- Trying to add data in unsupported state
AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20).
Data as JSON: /api/errors/933cc676394b6c5b.
Report an issue: GitHub.