"}}]}]}

withastro/astro · error · Error

<script src=" "> references an asset in the " " directory…

Error message


<script src="${src}"> references an asset in the "${publicDir}" directory. Please add the "is:inline" directive to keep this asset from being bundled.

File: ${id}

What it means

Astro bundles processed <script> tags (those without is:inline). If such a script's src is an absolute path (/...) that does not point inside the source root (src/ by default), Astro concludes it references a file in the public directory. public/ assets are copied verbatim and are outside the module graph, so Vite cannot bundle them — the build stops and asks you to keep the script as-is with the is:inline directive.

Solutions

  1. Add the is:inline directive: <script is:inline src="/js/analytics.js"></script>
  2. Or move the file out of public/ into the source tree (e.g. src/scripts/analytics.js) and reference it relatively so Vite bundles it
  3. Keep third-party CDN scripts (full https:// URLs) as-is; only root-relative /... paths that resolve into public/ hit this error

Example fix

<!-- before -->
<script src="/js/analytics.js"></script>

<!-- after -->
<script is:inline src="/js/analytics.js"></script>
Defensive patterns

Strategy: validation

Validate before calling

// check whether a root-relative src points into public/ before writing the tag
import fs from 'node:fs';
import path from 'node:path';
const isPublicAsset = (src: string) =>
	src.startsWith('/') && fs.existsSync(path.join('public', src));
// isPublicAsset('/js/analytics.js') === true -> needs is:inline

Prevention

When it happens

Trigger: <script src="/js/analytics.js"></script> where the file lives at public/js/analytics.js; moving a bundled script into public/ without adding is:inline; root-relative paths to vendor files dropped into public/.

Common situations: Pasting <script src="..."> snippets from vendor docs into an .astro layout; migrating a static site whose scripts all lived in the public folder.

Related errors


AI-assisted analysis of withastro/astro@52e6c34790 (2026-08-18). Data as JSON: /api/errors/442b9f72acee55a7. Report an issue: GitHub.

Appendix: source

Thrown at packages/astro/src/vite-plugin-astro/index.ts:213

							// SSR script only exists to make them appear in the module graph.
							if (isAstroServerEnvironment(this.environment)) {
								return {
									code: `/* client script, empty in SSR: ${id} */`,
									moduleType: 'ts',
								};
							}

							const script = compileMetadata.scripts[query.index];
							if (!script) {
								throw new Error(`No script at index ${query.index}`);
							}

							if (script.type === 'external') {
								const src = script.src!;
								if (src.startsWith('/') && !isBrowserPath(src)) {
									const publicDir =
										config.publicDir.pathname.replace(/\/$/, '').split('/').pop() + '/';
									throw new Error(
										`\n\n<script src="${src}"> references an asset in the "${publicDir}" directory. Please add the "is:inline" directive to keep this asset from being bundled.\n\nFile: ${id}`,
									);
								}
							}

							const result: vite.Rolldown.SourceDescription = {
								code: '',
								moduleType: 'ts',
								meta: {
									vite: {
										lang: 'ts',
									},
								},
							};

							switch (script.type) {
								case 'inline': {
									result.code = script.code ?? '';

View on GitHub (pinned to 52e6c34790)