diff --git a/packages/vite/src/node/plugins/html.ts b/packages/vite/src/node/plugins/html.ts
index 537f58470a9cbd..7d44c91280f9b3 100644
--- a/packages/vite/src/node/plugins/html.ts
+++ b/packages/vite/src/node/plugins/html.ts
@@ -534,8 +534,11 @@ export function buildHtmlPlugin(config: ResolvedConfig): Plugin {
const processedEncodedUrl = await processSrcSet(
attr.value,
async ({ url }) => {
- const decodedUrl = decodeURI(url)
- if (!isExcludedUrl(decodedUrl)) {
+ const decodedUrl = decodeURIIfPossible(url)
+ if (
+ decodedUrl !== undefined &&
+ !isExcludedUrl(decodedUrl)
+ ) {
const result = await processAssetUrl(url)
return result !== decodedUrl
? encodeURIPath(result)
@@ -550,8 +553,10 @@ export function buildHtmlPlugin(config: ResolvedConfig): Plugin {
})(),
)
} else if (attr.type === 'src') {
- const url = decodeURI(attr.value)
- if (checkPublicFile(url, config)) {
+ const url = decodeURIIfPossible(attr.value)
+ if (url === undefined) {
+ // ignore it
+ } else if (checkPublicFile(url, config)) {
overwriteAttrValue(
s,
attr.location,
@@ -1580,3 +1585,12 @@ function serializeAttrs(attrs: HtmlTagDescriptor['attrs']): string {
function incrementIndent(indent: string = '') {
return `${indent}${indent[0] === '\t' ? '\t' : ' '}`
}
+
+function decodeURIIfPossible(input: string): string | undefined {
+ try {
+ return decodeURI(input)
+ } catch {
+ // url is malformed, probably a interpolate syntax of template engines
+ return
+ }
+}