vitejs/vite · error · Error

{ runtime: "${result.runtime}" } is not supported for assets

Error message

{ runtime: "${result.runtime}" } is not supported for assets in ${hostType} files: ${filename}

What it means

In toOutputFilePathWithoutRuntime (build.ts:1707-1717), when the experimental.renderBuiltUrl hook returns an object containing a runtime property for an asset, Vite throws. Runtime-lazy URL resolution ({ runtime }) is only meaningful for JS module imports, not for assets referenced inside CSS/HTML/JS host files at build time, so it is rejected for assets.

Source

Thrown at packages/vite/src/node/build.ts:1715

  filename: string,
  type: 'asset' | 'public',
  hostId: string,
  hostType: 'js' | 'css' | 'html',
  config: ResolvedConfig,
  toRelative: (filename: string, hostId: string) => string,
): string {
  const { renderBuiltUrl } = config.experimental
  let relative = config.base === '' || config.base === './'
  if (renderBuiltUrl) {
    const result = renderBuiltUrl(filename, {
      hostId,
      hostType,
      type,
      ssr: !!config.build.ssr,
    })
    if (typeof result === 'object') {
      if (result.runtime) {
        throw new Error(
          `{ runtime: "${result.runtime}" } is not supported for assets in ${hostType} files: ${filename}`,
        )
      }
      if (typeof result.relative === 'boolean') {
        relative = result.relative
      }
    } else if (result) {
      return result
    }
  }
  if (relative && !config.build.ssr) {
    return toRelative(filename, hostId)
  } else {
    return joinUrlSegments(config.decodedBase, filename)
  }
}

export const toOutputFilePathInCss: typeof toOutputFilePathWithoutRuntime =

View on GitHub (pinned to 89620f09af)

Solutions

  1. For assets, return a plain string URL or an object with only { relative } — never { runtime }.
  2. Restrict { runtime } returns to non-asset (JS import) contexts by checking the type argument.
  3. If you need runtime resolution, handle it in client code rather than via renderBuiltUrl for assets.

Example fix

// before
renderBuiltUrl(filename, { type, hostType }) {
  return { runtime: `import.meta.env.BASE_URL + '${filename}'` } // throws for assets
}
// after
renderBuiltUrl(filename, { type }) {
  if (type === 'asset') return `/assets/${filename}` // string only
  return { runtime: `import.meta.env.BASE_URL + '${filename}'` }
}
Defensive patterns

Strategy: type-guard

Validate before calling

experimental: {
  renderBuiltUrl(filename, { type }) {
    if (type === 'asset') return undefined // let Vite default
    return undefined
  }
}

Type guard

function isSafeAssetResult(result: unknown): boolean {
  return !(typeof result === 'object' && result !== null && 'runtime' in result)
}

Prevention

When it happens

Trigger: Implementing experimental.renderBuiltUrl and returning { runtime: '...' } for a file whose type is 'asset' (i.e. for an asset URL computed while rendering a js/css/html host file).

Common situations: Customizing built asset URLs via renderBuiltUrl and accidentally returning a runtime value for static assets; copying a runtime pattern valid for JS imports into asset handling.

Related errors


AI-assisted analysis of vitejs/vite@89620f09af (2026-08-03). Data as JSON: /data/errors/9c54ef6e45e56b9b.json. Report an issue: GitHub.