{"record":{"id":"4a030f9ec67c941f","repo":"sveltejs/kit","slug":"relative-is-missing-tag","errorCode":null,"errorMessage":"${relative} is missing ${tag}","messagePattern":"(.+?) is missing (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/kit/src/core/config/index.js","lineNumber":89,"sourceCode":" * required content.\n * @param {string} cwd\n * @param {ValidatedConfig} config\n */\nexport function load_template(cwd, config) {\n\tconst { files } = config;\n\n\tconst relative = path.relative(cwd, files.appTemplate);\n\n\tif (!fs.existsSync(files.appTemplate)) {\n\t\tthrow new Error(`${relative} does not exist`);\n\t}\n\n\tconst contents = fs.readFileSync(files.appTemplate, 'utf8');\n\n\tconst expected_tags = ['%sveltekit.head%', '%sveltekit.body%'];\n\texpected_tags.forEach((tag) => {\n\t\tif (contents.indexOf(tag) === -1) {\n\t\t\tthrow new Error(`${relative} is missing ${tag}`);\n\t\t}\n\t});\n\n\treturn contents;\n}\n\n/**\n * Loads the error page (src/error.html by default) if it exists.\n * Falls back to a generic error page content.\n * @param {ValidatedConfig} config\n */\nexport function load_error_page(config) {\n\tlet { errorTemplate } = config.files;\n\n\t// Don't do this inside resolving the config, because that would mean\n\t// adding/removing error.html isn't detected and would require a restart.\n\tif (!fs.existsSync(config.files.errorTemplate)) {\n\t\terrorTemplate = url.fileURLToPath(new URL('./default-error.html', import.meta.url));","sourceCodeStart":71,"sourceCodeEnd":107,"githubUrl":"https://github.com/sveltejs/kit/blob/03f1687fe612ce3d2d9131139b5b188d9cf90c64/packages/kit/src/core/config/index.js#L71-L107","documentation":"The app template must contain the placeholders %sveltekit.head% and %sveltekit.body% so SvelteKit can inject the page head and rendered body. load_template reads the template and throws if either placeholder is missing, because rendering would silently produce broken pages otherwise.","triggerScenarios":"write_server -> load_template reads files.appTemplate successfully, but its contents do not include `%sveltekit.head%` or `%sveltekit.body%` (indexOf returns -1 for either tag).","commonSituations":"Users copy a plain HTML file as app.html without the placeholders; manually stripping tags when 'cleaning up' the file; using a template written for an older framework version; tooling that minifies/rewrites the file and removes the tokens.","solutions":["Add the missing placeholder(s) into the template: `%sveltekit.head%` inside <head> and `%sveltekit.body%` inside <body> (wrapped in a div or body content).","Restore the default src/app.html from the SvelteKit template (`npx sv create` output or the docs) if unsure of the shape.","Check for preprocessing/formatting tools that might strip the placeholder comments/tokens and exclude app.html from them."],"exampleFix":"<!-- before: src/app.html missing placeholders -->\n<html><head></head><body><div id=\"app\"></div></body></html>\n<!-- after -->\n<html><head>%sveltekit.head%</head><body data-sveltekit-preload-data=\"hover\"><div style=\"display: contents\">%sveltekit.body%</div></body></html>","handlingStrategy":"validation","validationCode":"import fs from 'node:fs';\nconst contents = fs.readFileSync('src/app.html', 'utf8');\nfor (const tag of ['%sveltekit.head%', '%sveltekit.body%']) {\n  if (!contents.includes(tag)) throw new Error(`src/app.html is missing ${tag}`);\n}","typeGuard":null,"tryCatchPattern":"try {\n  await viteBuild();\n} catch (e) {\n  if (e.message.includes('is missing %sveltekit.')) {\n    console.error('Add the missing %sveltekit.head% / %sveltekit.body% placeholder to app.html');\n  }\n  throw e;\n}","preventionTips":["Keep the standard placeholders in app.html whenever editing it","Start edits from the official default template","Exclude app.html from minifiers/transformers that might strip tokens","Add a smoke test asserting both placeholders exist in the template"],"tags":["config","template","build-time","placeholder"],"backgroundTag":"missing-template-placeholder","analyzedSha":"03f1687fe612ce3d2d9131139b5b188d9cf90c64","analyzedAt":"2026-09-02T02:01:50.504Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T06:17:21.866Z"}