NativeScript/NativeScript · error · Error

Failed to execute 'decode' on 'TextDecoder': The provided va

Error message

Failed to execute 'decode' on 'TextDecoder': The provided value is not of type '(ArrayBuffer or ArrayBufferView)'

What it means

The TextDecoder shim in @nativescript/core validates that the input to decode() resolves to a real ArrayBuffer (after unwrapping ArrayBufferViews via input.buffer). If the argument is not an ArrayBuffer or typed view — e.g. a plain number, string, null, or an array-like — it throws this Web-API-compatible TypeError-like Error.

Source

Thrown at packages/core/text/text-common.ts:72

	}
	if (point <= 0x007f) {
		return nonAsciiChars;
	} else if (point <= 0x07ff) {
		return String.fromCharCode((0x6 << 5) | (point >>> 6), (0x2 << 6) | (point & 0x3f));
	} else {
		return String.fromCharCode((0xe /*0b1110*/ << 4) | (point >>> 12), (0x2 /*0b10*/ << 6) | ((point >>> 6) & 0x3f) /*0b00111111*/, (0x2 /*0b10*/ << 6) | (point & 0x3f) /*0b00111111*/);
	}
}

export class TextDecoder {
	public get encoding() {
		return 'utf-8';
	}

	public decode(input: BufferSource): string {
		const buffer = ArrayBuffer.isView(input) ? input.buffer : input;
		if (Object_prototype_toString.call(buffer) !== ArrayBufferString) {
			throw Error("Failed to execute 'decode' on 'TextDecoder': The provided value is not of type '(ArrayBuffer or ArrayBufferView)'");
		}
		const inputAs8 = new Uint8Array(buffer);
		let resultingString = '';
		for (let index = 0, len = inputAs8.length | 0; index < len; index = (index + 32768) | 0) {
			resultingString += String.fromCharCode.apply(0, inputAs8.slice(index, (index + 32768) | 0));
		}

		return resultingString.replace(/[\xc0-\xff][\x80-\xbf]*/g, decoderReplacer);
	}

	public toString() {
		return '[object TextDecoder]';
	}

	[Symbol.toStringTag] = 'TextDecoder';
}

export class TextEncoder {

View on GitHub (pinned to 6800aefa65)

Solutions

  1. Ensure you pass an ArrayBuffer or a typed array (Uint8Array etc.); wrap raw bytes with new Uint8Array(bytes).decode via new TextDecoder().decode(new Uint8Array(raw)).
  2. If you have an ArrayBuffer with offset, pass new Uint8Array(buffer, byteOffset, byteLength) rather than a plain object.
  3. If input may be a string, decode differently (it's already text) or encode it first with new TextEncoder().encode(str).
  4. Guard before calling: check input instanceof ArrayBuffer || ArrayBuffer.isView(input).

Example fix

// before
const text = decoder.decode(await response.arrayBuffer().then(b => b.byteLength));
// after
const buf = await response.arrayBuffer();
const text = decoder.decode(new Uint8Array(buf));
Defensive patterns

Strategy: type-guard

Validate before calling

function isBufferSource(v: unknown): v is ArrayBuffer | ArrayBufferView {
  return v instanceof ArrayBuffer || (ArrayBuffer.isView(v as any));
}
if (!isBufferSource(input)) throw new TypeError('decode expects ArrayBuffer or ArrayBufferView');

Type guard

function isBufferSource(v: unknown): v is ArrayBuffer | ArrayBufferView {
  return v instanceof ArrayBuffer || ArrayBuffer.isView(v as any);
}

Try / catch

try {
  const text = decoder.decode(input);
} catch (e) {
  if (e.message.includes("'decode' on 'TextDecoder'")) {
    console.error('decode() needs ArrayBuffer/typed array, got:', typeof input);
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling textDecoder.decode(x) where x is not BufferSource: a plain string, number, null/undefined, a Node Buffer from a different realm whose .buffer isn't a real ArrayBuffer, or a plain array.

Common situations: Decoding HTTP/socket data where a string was passed instead of bytes; passing a Node.js Buffer in an environment where ArrayBuffer.toString tag check fails; off-by-one code that decode()'s byteOffset slices incorrectly (e.g. slicing to a number instead of a view).

Related errors


AI-assisted analysis of NativeScript/NativeScript@6800aefa65 (2026-08-30). Data as JSON: /api/errors/aa6179ba0d5fc357. Report an issue: GitHub.