drizzle-team/drizzle-orm · critical · Error

TextDecoder is not available. Please provide either Buffer o

Error message

TextDecoder is not available. Please provide either Buffer or TextDecoder polyfill.

What it means

Thrown by normalizeFieldValue in the LibSQL session (line 324) when a returned value is an ArrayBuffer but neither Buffer (Node) nor TextDecoder (browser/modern runtimes) is available to decode it. This is purely an environment capability gap - the runtime lacks the global APIs Drizzle needs to materialize binary column data.

Source

Thrown at drizzle-orm/src/libsql/session.ts:324

		if (Object.prototype.propertyIsEnumerable.call(obj, key)) {
			acc[key] = obj[key];
		}
		return acc;
	}, {});
}

function normalizeFieldValue(value: unknown) {
	if (typeof ArrayBuffer !== 'undefined' && value instanceof ArrayBuffer) { // eslint-disable-line no-instanceof/no-instanceof
		if (typeof Buffer !== 'undefined') {
			if (!(value instanceof Buffer)) { // eslint-disable-line no-instanceof/no-instanceof
				return Buffer.from(value);
			}
			return value;
		}
		if (typeof TextDecoder !== 'undefined') {
			return new TextDecoder().decode(value);
		}
		throw new Error('TextDecoder is not available. Please provide either Buffer or TextDecoder polyfill.');
	}
	return value;
}

View on GitHub (pinned to b7862528fd)

Solutions

  1. Add a TextDecoder polyfill to your runtime/bundle (e.g. fast-text-encoding) so globalThis.TextDecoder is defined.
  2. If on Node, ensure Buffer is available - avoid bundlers that strip node:buffer.
  3. Run on a runtime that ships TextDecoder natively (modern browsers, Node 18+, Cloudflare Workers, Deno).
  4. Avoid selecting BLOB columns if you cannot provide a decoder, or cast them to text in SQL.

Example fix

// before - runtime lacks TextDecoder
// Error: TextDecoder is not available...

// after - install a polyfill before any query
import 'fast-text-encoding'; // adds global TextDecoder
// or in entry:
globalThis.TextDecoder = globalThis.TextDecoder || (await import('util')).TextDecoder;
await db.select().from(files).where(eq(files.id, id));
Defensive patterns

Strategy: validation

Validate before calling

// Ensure a decoder exists before running queries
const hasDecoder = typeof Buffer !== 'undefined' || typeof TextDecoder !== 'undefined';
if (!hasDecoder) {
  throw new Error('Install a TextDecoder polyfill (e.g. fast-text-encoding).');
}

Type guard

function hasBinaryDecoder(): boolean {
  return typeof Buffer !== 'undefined' || typeof TextDecoder !== 'undefined';
}

Prevention

When it happens

Trigger: A LibSQL query returns a binary/blob column whose value arrives as ArrayBuffer, and the JS runtime exposes neither global Buffer nor global TextDecoder. Common in stripped-down or non-standard runtimes.

Common situations: Running Drizzle + LibSQL on an edge runtime or custom embedded JS engine that lacks TextDecoder; bundling with aggressive polyfill stripping that removes Node Buffer; older environments without TextDecoder support.

Related errors


AI-assisted analysis of drizzle-team/drizzle-orm@b7862528fd (2026-08-03). Data as JSON: /data/errors/9860629a1ca2a5d8.json. Report an issue: GitHub.