evanw/esbuild · error

Invalid fallback path: %s

Error message

Invalid fallback path: %s

What it means

Returned by internalContext.Serve when serveOptions.Fallback is non-empty but ctx.realFS.Abs(Fallback) fails to absolutize it. The fallback is the file served when a request doesn't match any built output (e.g. for SPA routing); esbuild requires it to be resolvable to an absolute path. The ok check at serve_other.go:760 returns false, triggering the error.

Source

Thrown at pkg/api/serve_other.go:763

	if (serveOptions.Keyfile != "") != (serveOptions.Certfile != "") {
		return ServeResult{}, errors.New("Must specify both key and certificate for HTTPS")
	}

	// Validate the "servedir" path
	if serveOptions.Servedir != "" {
		if absPath, ok := ctx.realFS.Abs(serveOptions.Servedir); ok {
			serveOptions.Servedir = absPath
		} else {
			return ServeResult{}, fmt.Errorf("Invalid serve path: %s", serveOptions.Servedir)
		}
	}

	// Validate the "fallback" path
	if serveOptions.Fallback != "" {
		if absPath, ok := ctx.realFS.Abs(serveOptions.Fallback); ok {
			serveOptions.Fallback = absPath
		} else {
			return ServeResult{}, fmt.Errorf("Invalid fallback path: %s", serveOptions.Fallback)
		}
	}

	// Validate the CORS origins
	for _, origin := range serveOptions.CORS.Origin {
		if star := strings.IndexByte(origin, '*'); star >= 0 && strings.ContainsRune(origin[star+1:], '*') {
			return ServeResult{}, fmt.Errorf("Invalid origin: %s", origin)
		}
	}

	// Stuff related to the output directory only matters if there are entry points
	outdirPathPrefix := ""
	if len(ctx.args.entryPoints) > 0 {
		// Don't allow serving when builds are written to stdout
		if ctx.args.options.WriteToStdout {
			what := "entry points"
			if len(ctx.args.entryPoints) == 1 {
				what = "an entry point"

View on GitHub (pinned to 6ff1d8b0d8)

Solutions

  1. Ensure the fallback file exists and is readable before calling Serve().
  2. Use an absolute path for Fallback to remove cwd ambiguity.
  3. If the fallback is a build output, run an initial build first so the file exists.
  4. Double-check the filename and extension for typos.

Example fix

// before
ctx.Serve({ Servedir: './www', Fallback: './www/index.htm' }); // typo: .htm not present

// after
ctx.Serve({ Servedir: './www', Fallback: path.resolve('./www/index.html') });
Defensive patterns

Strategy: validation

Validate before calling

const fs = require('fs');
if (serveOpts.Fallback) {
  const abs = path.resolve(serveOpts.Fallback);
  if (!fs.existsSync(abs)) throw new Error('fallback file missing');
  serveOpts.Fallback = abs;
}

Type guard

function isFallbackPathError(e) { return /Invalid fallback path/.test(e?.message || ''); }

Try / catch

try { await ctx.Serve({ Fallback }); } catch (e) { if (isFallbackPathError(e)) { /* generate or fix the fallback file, then retry */ } throw e; }

Prevention

When it happens

Trigger: Calling ctx.Serve({ Fallback: './index.html' }) where the fallback path does not exist or cannot be resolved by realFS.Abs. The guard at serve_other.go:760 fails.

Common situations: The fallback file doesn't exist (typo, not generated yet); relative path that doesn't resolve from esbuild's cwd; pointing Fallback at a file the build will produce before the first build has run; permissions blocking stat.

Related errors


AI-assisted analysis of evanw/esbuild@6ff1d8b0d8 (2026-08-03). Data as JSON: /data/errors/b96635d04d122a1e.json. Report an issue: GitHub.