denoland/deno · error
ERR_INDEX_OUT_OF_RANGE
ERR_INDEX_OUT_OF_RANGE
Error message
Index out of range
What it means
Buffer hex-encoding (toString('hex', start, end)) validates slice bounds: negative start or end values are out of range because slice indices must be non-negative byte offsets. hexIndexOutOfRange() throws ERR_INDEX_OUT_OF_RANGE to match Node's behavior rather than silently clamping.
Source
Thrown at ext/node/polyfills/internal/buffer.mjs:1269
function hexIndexOutOfRange() {
const err = new RangeError("Index out of range");
err.code = "ERR_OUT_OF_RANGE";
return err;
}
Buffer.prototype.hexSlice = function hexSlice(start, end) {
let byteLength = TypedArrayPrototypeGetByteLength(this);
// Index semantics replicate Node's C++ StringSlice: zero-length receivers
// (including detached) return "" before any validation, ToInteger
// coercion, negative index throws "Index out of range", end < start
// clamps to empty, and only a forward range with end > length throws.
if (byteLength === 0) {
return "";
}
start = start === undefined ? 0 : MathTrunc(Number(start)) || 0;
end = end === undefined ? byteLength : MathTrunc(Number(end)) || 0;
if (start < 0 || end < 0) {
throw hexIndexOutOfRange();
}
if (end <= start) {
return "";
}
// Re-read: argument coercion can run user code that resizes or detaches
// the underlying buffer (detached views report length 0).
byteLength = TypedArrayPrototypeGetByteLength(this);
if (end > byteLength) {
throw hexIndexOutOfRange();
}
if (end - start > kStringMaxLength / 2) {
throw genericNodeError(
`Cannot create a string longer than 0x${
NumberPrototypeToString(kStringMaxLength, 16)
} characters`,
{ code: "ERR_STRING_TOO_LONG" },
);
}View on GitHub (pinned to a961cdec3b)
Solutions
- Clamp indices before the call: start = Math.max(0, start); end = Math.max(0, end).
- Fix the index arithmetic so start/end are non-negative byte offsets within [0, byteLength].
- Coerce with MathTrunc and validate user-supplied indices before use.
Example fix
// before
const hex = buf.toString('hex', 0, buf.length - 8); // negative when short
// after
const end = Math.max(0, buf.byteLength - 8);
const hex = buf.toString('hex', 0, end); Defensive patterns
Strategy: validation
Validate before calling
function clampHexRange(buf, start = 0, end = buf.byteLength) {
start = Math.max(0, Math.trunc(start) || 0);
end = Math.max(0, Math.trunc(end) || 0);
return [start, Math.min(end, buf.byteLength)];
}
const [s, e] = clampHexRange(buf, userStart, userEnd);
const hex = buf.toString('hex', s, e); Type guard
function isSafeIndex(v) {
return Number.isInteger(v) && v >= 0;
} Try / catch
try {
hex = buf.toString('hex', start, end);
} catch (err) {
if (err.code === 'ERR_INDEX_OUT_OF_RANGE') {
[start, end] = clampHexRange(buf, start, end);
hex = buf.toString('hex', start, end);
}
} Prevention
- Clamp all slice indices to [0, byteLength] before calling toString.
- Avoid negative-index arithmetic styles from other languages (Python slicing).
- Guard computed ends like length - n with Math.max(0, ...).
When it happens
Trigger: Calling buf.toString('hex', start, end) with a negative start or a negative end — e.g. end computed as buf.length - extra where extra > length, or -1 passed as an end sentinel.
Common situations: Off-by-one arithmetic producing negative end; porting code that used negative indices like Python/JS array slicing; uninitialized length variables.
Related errors
- ERR_INVALID_ARG_TYPE
- invalid ${name}, must not be infinity or NaN
- ERR_INVALID_ARG_VALUE
- ERR_INVALID_HTTP_TOKEN
- ERR_INVALID_HTTP_TOKEN
AI-assisted analysis of denoland/deno@a961cdec3b (2026-09-03).
Data as JSON: /api/errors/b67dace5be4a0abe.
Report an issue: GitHub.