Skip to content

"Argument is not valid" for items without v-svg-inline directive #18

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
tomastan opened this issue Oct 4, 2022 · 13 comments
Open

"Argument is not valid" for items without v-svg-inline directive #18

tomastan opened this issue Oct 4, 2022 · 13 comments

Comments

@tomastan
Copy link

tomastan commented Oct 4, 2022

We noticed some random JS exceptions in Sentry logs which made us a bit confused.

For example:
TypeError: [vue-svg-inline-plugin] Argument is not valid! [path="/image/i.702/w.400:h.400:f.0/image.png"]

The confusion is because this element does not contain SVG and should not be affected at all:

<img v-lazy="getImageUrl(item.image_id)">

The same Vue component contains other elements using vue-svg-inline-plugin, for example:

<img v-svg-inline src="/customer/images/challenge-success.svg" alt="">
<img v-svg-inline src="/customer/images/challenge-failed.svg" alt="">

Any ideas?

@oliverfindl
Copy link
Owner

Hello,

this error means, that plugin expects SVG file, but got something else (in your case PNG).

const REGEXP_SVG_FILENAME = /.+\.svg(?:[?#].*)?$/i;

/* throw error if path argument is not valid */
if(!REGEXP_SVG_FILENAME.test(path)) throw new TypeError(`[${PACKAGE_NAME}] Argument is not valid! [path="${path}"]`);

Are you 100% sure, its coming from this part of code?

<img v-lazy="getImageUrl(item.image_id)">

Because this plugin registers its own Vue directive and should not run outside of it. If you are able to reproduce this issue, please try to add console.log({ node, directives }); after this line (edit this file directly in node_modules):

/* store vnode directives reference based on Vue version */
const directives = isVue3 ? vnode.dirs : vnode.data.directives;

To see if there is actually processed image node without chosen directive.

Thanks.

@tomastan
Copy link
Author

tomastan commented Oct 5, 2022

@oliverfindl what I'm sure is that we set directive on svg files only (see screen below). That why my own confusion comes from :).
It's very hard to reproduce as it occures randomly on a production server with more usage. But I'll try to look if I can catch it on my dev environment to give more debugging information.

image

@tomastan
Copy link
Author

tomastan commented Nov 7, 2022

I managed to explore the issue a bit more and get it replicated. Seems there is some conflict with vue-lazyload package in my case.

The simplified block that reproduces the issue is this:

<template>
	<div>
		<div v-if="showBlock=='default'">
			<img v-lazy="getImageUrl(item.image_id)">
		</div>

		<div v-if="showBlock=='failed'">
			<img v-svg-inline src="/customer/images/challenge-failed.svg" alt="">
		</div>
	</div>
</template>

On showBlock=="default" a PNG image is loaded externally with a vue-lazyload. And after showBlock="failed" it should show a static SVG, which is works, but the beforementioned error is thrown.

If instead of <img v-lazy="getImageUrl(item.image_id)"> a simple <img :src="getImageUrl(item.image_id)"> is used, the problem does not happen. So somehow these two elements collide with each other.

As you proposed in console.log() into the beforeMount() method so the output if here:
image

@oliverfindl
Copy link
Owner

Hello,

this looks really strange. Can you also expand img node in console? And please, send me exact version of vue-lazyload, so I can also replicate this issue locally.

Thanks.

@Ilya-Chernyshev
Copy link

I also ran into this problem. I used standard settings and only svg files

image

image

@Ilya-Chernyshev
Copy link

Ilya-Chernyshev commented Nov 8, 2022

The solution to the problem was to set the data-src attribute. And the installation of version 2.2.2. But there was another error in the console.

On version 2.2.3. does not work.

image

@tomastan
Copy link
Author

tomastan commented Nov 9, 2022

@oliverfindl the object is pretty large so does not fit to the screen, so cant copy it all here
image

But something useful is here maybe. Yes - dataset contains wrong value.
image

We use vue-lazyload 1.3.4 (the latest one for vue 2)

@tomastan
Copy link
Author

tomastan commented Nov 9, 2022

FYI, the resulting element in DOM looks like this:

<img data-src="/image/i.167/w.400:h.400:f.0/image.png"
src="https://aimera.local/customer/images/challenge-failed.svg" lazy="error" alt="">

@oliverfindl
Copy link
Owner

Hello @tomastan,

I created a dummy document and unfortunately I can't replicate your issue. I had to use version 1.3.3, because 1.3.4 was throwing error: [Vue warn]: Failed to resolve directive: lazy vue.js.

<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8">
		<meta http-equiv="X-UA-Compatible" content="IE=edge">
		<meta name="viewport" content="width=device-width, initial-scale=1.0">
		<title>Document</title>
		<style>img, svg { max-height: 200px; }</style>
	</head>
	<body>
		<div id="app">
			<img v-svg-inline :src="svg" />
			<img v-lazy="png" />
		</div>
		<script src="https://unpkg.com/[email protected]/dist/vue-svg-inline-plugin.min.js"></script>
		<script src="https://unpkg.com/[email protected]/vue-lazyload.js"></script>
		<script src="https://unpkg.com/[email protected]/dist/vue.js"></script>
		<script>
			Vue.use(VueSvgInlinePlugin);
			Vue.use(VueLazyload);
			new Vue({
				data: {
					svg: "https://raw.githubusercontent.com/vuejs/art/master/logo.svg",
					png: "https://raw.githubusercontent.com/vuejs/art/master/logo.png"
				}
			}).$mount("#app");
		</script>
	</body>
</html>

Please provide minimal example, so I can replicate this issue.

Thanks.

@oliverfindl
Copy link
Owner

Hello @Ilya-Chernyshev,

this is different issue. There was already reported something similar, which was related to Vite due to using esbuild for dev server and Rollup for production build. Most probably your issue is related to your bundler. Please as first step, try to investigate your rendered webpage and try to find what is actually set into src attribute of img tag. You can also look at network tab for version 2.2.2, find requested URL for your SVG and modify your bundler accordingly. Furthermore, if you can't debug it yourself, please create a new issue as this not related to this one and provide minimal reproduction repository with your bundler, so I can examine its config and replicate this issue.

Thanks.

@tomastan
Copy link
Author

@oliverfindl I made a jsfiddle (https://jsfiddle.net/kpjzhotf/1/) for you. The key factor for this to happen is switching between two parent elements containing lazyloaded png in one, and inline-svg in the another. I have no idea, how these elements are related, but they do somehow. Maybe some Vue optimizers in force?

      <div v-if="!showSvg">
        <img v-lazy="png" />
      </div>
      
      <div v-if="showSvg">
        <img v-svg-inline :src="svg" />
      </div>

@oliverfindl
Copy link
Owner

Hello,

thanks for clarification. I found out, that you don't need to use v-lazy directive to trigger this behaviour, just replace v-lazy with :src and its still happening.

I presume, its due to how Vue is referencing elements. Our problem here is, that this plugin creates new svg node and replaces original img node with it, while Vue doesn't have any clue whats happening. Later it tries to change only attribute, that has changed and not whole node. And most probably, Vue still keeps reference for original img node, that is now detached from DOM.

I also tested your example with Vue 3 and its working there correctly. Unfortunately, I don't have any solution for Vue 2 based projects.

If you have more questions, feel free to ask here.

Thanks.

@tomastan
Copy link
Author

tomastan commented Nov 11, 2022

I somehow cannot replicate the issue with :src, for me no errors thrown. Would be interesting to see.

However, I also think there is something is with Vue internals. But this bring me to a solution. If key property is added to v-if blocks the optimization is avoided and issue is does not happen. So this may be useful for other:

<div v-if="!showSvg" key="svg">
    <img v-lazy="png" />
</div>
      
<div v-if="showSvg" key="png">
    <img v-svg-inline :src="svg" />
</div>

Working example: https://jsfiddle.net/x0trzuaj/1/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants