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-ignoreView on GitHub (pinned to 20b341f100)
Solutions
- Ensure the source passed to `parse`/`compile`/`preprocess` is a string — call `.toString('utf8')` on Buffers and `.toString()` on string-like values.
- Add a typeof check before calling compile and surface a clearer upstream error.
- 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
- Always pass an encoding to `fs.readFileSync(path, 'utf8')` so the result is a string.
- Add a typeof guard at the boundary of any tool that feeds the compiler.
- Normalize inputs in preprocessors — never forward Buffers or null to `compile`/`parse`.
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
- 'svelte/compiler' no longer exports a `walk` utility — pleas
- rune_outside_svelte
- experimental_async_required
AI-assisted analysis of sveltejs/svelte@20b341f100 (2026-08-12).
Data as JSON: /api/errors/3f4a837bcc2d61f6.
Report an issue: GitHub.