drizzle-team/drizzle-orm · critical · Error

TextDecoder is not available. Please provide either Buffer…

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.

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: /api/errors/9860629a1ca2a5d8. Report an issue: GitHub.

Appendix: 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)