sveltejs/svelte · error · TypeError

Template must be a string

Error message

Template must be a string

What it means

The parser's `Template` constructor requires the component source to be a string and throws a `TypeError` otherwise. This is a hard precondition guard at the entry of phase-1 parsing; the parser does not attempt coercion or defaulting. It is the first check before `template.trimEnd()` and language detection.

Source

Thrown at packages/svelte/src/compiler/phases/1-parse/index.js:95

	/** @type {AST.Fragment[]} */
	fragments = [];

	/** @type {AST.Root} */
	root;

	/** @type {Record<string, boolean>} */
	meta_tags = {};

	/** @type {LastAutoClosedTag | undefined} */
	last_auto_closed_tag;

	/**
	 * @param {string} template
	 * @param {boolean} loose
	 */
	constructor(template, loose) {
		if (typeof template !== 'string') {
			throw new TypeError('Template must be a string');
		}

		this.loose = loose;
		this.template = template.trimEnd();

		let match_lang;

		do match_lang = regex_lang_attribute.exec(template);
		while (match_lang && match_lang[0][1] !== 's'); // ensure it starts with '<s' to match script tags

		regex_lang_attribute.lastIndex = 0; // reset matched index to pass tests - otherwise declare the regex inside the constructor

		this.ts = match_lang?.[2] === 'ts';

		this.root = {
			css: null,
			js: [],
			// @ts-ignore

View on GitHub (pinned to 20b341f100)

Solutions

  1. Ensure the source passed to `parse`/`compile`/`preprocess` is a string — call `.toString('utf8')` on Buffers and `.toString()` on string-like values.
  2. Add a typeof check before calling compile and surface a clearer upstream error.
  3. When using `fs.readFileSync`, pass `'utf8'` as the encoding so the result is already a string.

Example fix

// before
import { readFileSync } from 'node:fs';
import { compile } from 'svelte/compiler';
const result = compile(readFileSync('./Comp.svelte')); // Buffer, not string

// after
const result = compile(readFileSync('./Comp.svelte', 'utf8'));
Defensive patterns

Strategy: type-guard

Validate before calling

// Validate before parsing.
import { compile } from 'svelte/compiler';
function safeCompile(filename, source) {
  if (typeof source !== 'string') {
    throw new TypeError(`${filename}: expected string source, got ${typeof source}`);
  }
  return compile(source, { filename });
}

Type guard

/** @param {unknown} s */
function isTemplateSource(s) {
  return typeof s === 'string';
}

if (!isTemplateSource(maybeSource)) {
  throw new TypeError('Template source must be a string');
}
parse(maybeSource);

Prevention

When it happens

Trigger: Calling `parse()` (or any compile entry point that constructs `Template`) with a non-string argument: `undefined`, `null`, a Buffer/Uint8Array, a number, or an already-parsed AST object. The `typeof template !== 'string'` branch fires.

Common situations: Tooling that reads a `.svelte` file as a Node `Buffer` and forgets to call `.toString()`; preprocessors returning the wrong shape; programmatic callers that pass `null` when a file is missing; or test fixtures loading files with `fs.readFileSync` without an encoding argument.

Related errors


AI-assisted analysis of sveltejs/svelte@20b341f100 (2026-08-12). Data as JSON: /api/errors/3f4a837bcc2d61f6. Report an issue: GitHub.