Barcode detection service unavailable
https://github.com/Sec-ant/barcode-detector/blob/ab876a6a19b610ed3ce4b69f8216ed3c878421f4/src/BarcodeDetector.ts#L140-L143
i used vue-qrcode-reader at https website
<qrcode-stream @detect="onDetect"></qrcode-stream>
it shows "Barcode detection service unavailable. Use 'setZXingModuleOverrides' in offline or strict CSP environments.", "NotSupportedError"
the host already set Strict-Transport-Security: max-age=31536000; includeSubdomains; preload
but the static js file not set
i see the demo website https://vue-qrcode-reader.netlify.app. it's doc and static js both set Strict-Transport-Security
how can i solve the detect error?
Hey, louie
I don't think Strict-Transport-Security is relevant here. "CSP" is short for "Content Security Policy".
This package uses WebAssembly to provide the core function of detecting barcodes. And the browser must instantiate and execute the WebAssembly module to use it. However, per the spec, websites can control whether to block the WebAssembly execution by setting the script-src directive in CSP, specifically the wasm-unsafe-eval or unsafe-eval source value. If it is blocked, the error Barcode detection service unavailable will get thrown.
The directive connect-src can also affect this package. To prevent bloating the size, this package will load the .wasm file from the cdn.jsdelivr.net CDN at runtime (using fetch). connect-src or default-src can restrict the URLs which can be loaded with fetch. So if this connection is somewhat get blocked, the service unavailable error will also be thrown.
There're corresponding ways in which you can solve this problem:
- If you have control on the website where you're using this package, you can modify the CSP of the site to allow
wasm-unsafe-eval. and make sureconnect-srcordefault-srcincludeshttps://cdn.jsdelivr.net. A detailed explanation can be found at https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy - If you don't want to load the
.wasmfile from a CDN. You can usesetZXingModuleOverridesexported byvue-qrcode-readerto change the location where the.wasmfile is hosted. For example, you can host the file on your website as an asset, etc.
If neither solves your problem, it would be great if you can provide the malfunctioning website so that I can dig into it and check whether there're some other bugs to fix.
import wasmFile from "../node_modules/@sec-ant/zxing-wasm/dist/reader/zxing_reader.wasm?url";
I would like to ask what the syntax (?url)is?
in vue-cli project
import wasmFile from "@sec-ant/zxing-wasm/dist/reader/zxing_reader.wasm?url";
it's show error:
* a in ./node_modules/@sec-ant/zxing-wasm/dist/reader/zxing_reader.wasm?url
To install it, you can run: npm install --save a
How do I import the wasm module correctly?
Ok you decide not to fetch the .wasm file from jsDelivr. There're some gotchas, so I'd like to explain more:
First, a question: I wonder if you want to inline the .wasm file inside your script output files or you want to host it as a binary file on your site, and fetch it from your site at runtime?
Inline
Inlining means encoding the .wasm file as a Base64 data url and hardcode this data url inside your script files. If you use a syntax like this:
import wasmFile from "...?url"
then you're inlining it. ?url is a syntax provided by build tools, like Vite, to transform assets into data urls. I'm not sure if vue-cli supports it. If it is supported, then the wasmFile will be a huge base64 encoded data url.
Afterwards, you use setZXingModuleOverrides + locateFile to relocate the fetching path to this data url:
setZXingModuleOverrides({
locateFile: (path, prefix) => {
if (path.endsWith(".wasm")) {
return wasmFile; // <= a huge Base64 encoded data url
}
return prefix + path;
},
});
A data url occupies a larger space than its binary form, and parsing a data url into binary data also consumes more CPU clocks. So, ideally, I suggest you to not use the inline form.
Binary
If you want to host it as a binary file on your site, then you need not to import it. You can just copy the .wasm file to your website's assets folder, e.g. public or assets, and use setZXingModuleOverrides + locateFile to relocate the fetching path like this:
setZXingModuleOverrides({
locateFile: (path, prefix) => {
if (path.endsWith(".wasm")) {
return "https://<your website host>/public/zxing_reader.wasm"; // <= where the .wasm file is at
}
return prefix + path;
},
});
Either way, CSP still applies. You have to make sure content-src and script-src are correctly configured to allow you fetching and executing it.
Second question: where is the .wasm file?
Normally, when you add vue-qrcode-reader as a dependency in your project, it will also download its dependencies inside node_modules folder, which includes barcode-detector. And barcode-detector in turn will download its dependency @sec-ant/zxing-wasm. This process is handled by the package manager automatically so you don't need to worry.
The .wasm file is published as an asset included in the package @sec-ant/zxing-wasm, therefore, the .wasm file can be found at this path:
<project root>/node_modules/@sec-ant/zxing-wasm/dist/reader/zxing_reader.wasm
BUT, I made a mistake not pinning the version. So, the .wasm file you found in <project root>/node_modules/@sec-ant/zxing-wasm may not be what vue-qrcode-reader expects (Sorry for this mistake, I'm going to fix this in the next version). Therefore, for now, I recommend you manually download the .wasm file with the correct version, from the CDN.
If you're using [email protected], the matching version is @sec-ant/[email protected], so you can download the zxing_reader.wasm file from any of the following CDN paths:
- UNPKG: https://unpkg.com/@sec-ant/[email protected]/dist/reader/zxing_reader.wasm
- jsDelivr: https://cdn.jsdelivr.net/npm/@sec-ant/[email protected]/dist/reader/zxing_reader.wasm
- Skypack: https://cdn.skypack.dev/@sec-ant/[email protected]/dist/reader/zxing_reader.wasm
Once you've downloaded the correct version of the .wasm file, you can inline or host it as you wish in your project.
Again, I'm really sorry for the inconvenience. Once the version problem is fixed and released in vue-qrcode-reader, you won't have to worry about downloading it with the matching version. You can just import or copy it from <project root>/node_modules/@sec-ant/zxing-wasm/dist/reader/zxing_reader.wasm.
Thank @Sec-ant
i just put zxing_reader.wasm at assets public folder and then
setZXingModuleOverrides({
locateFile: (path, prefix) => {
if (path.endsWith(".wasm")) {
return '/zxing_reader.wasm';
}
return prefix + path;
},
});
my project site can request zxing_reader.wasm now.but it's still has error "Barcode detection service unavailable. Use 'setZXingModuleOverrides' in offline or strict CSP environments."
if the zxing_reader.wasm not from CDN and CSP not configured .Is this error still here?
Then this may be some other bug. To solve this problem I'll need more information.
-
If this issue is OS/browser related
For example, is the demo page of vue-qrcode-reader works on the same device? If it doesn't, then it's probably device related, and then I need the versions of the device's OS and browser.
-
If the error only occurs in your project site
Then it would be very helpful for you to share a repo to let me reproduce this problem, or share your site so that I can debug.
Then this may be some other bug. To solve this problem I'll need more information.
- If this issue is OS/browser related For example, is the demo page of vue-qrcode-reader works on the same device? If it doesn't, then it's probably device related, and then I need the versions of the device's OS and browser.
- If the error only occurs in your project site Then it would be very helpful for you to share a repo to let me reproduce this problem, or share your site so that I can debug.
yes.same device. vue-qrcode-reader demo page no exception
In that case, can you share a repro :)
In that case, can you share a repro :)
Ok .i send email to you
@louie0086 Can you try [email protected] (matches with @sec-ant/[email protected]) and see if this error still exists? If the error still exists, can you find more error information in the console?
@louie0086 Can you try
[email protected](matches with@sec-ant/[email protected]) and see if this error still exists? If the error still exists, can you find more error information in the console?
i updated @sec-ant/[email protected] and copy zxing_reader.wasm to zxing_reader1.wasm
still
setZXingModuleOverrides({
locateFile: (path, prefix) => {
if (path.endsWith(".wasm")) {
return '/zxing_reader1.wasm';
}
return prefix + path;
},
});
now it show
"Barcode detection service unavailable.",
"NotSupportedError"
I added this line of code to log a detailed error information, can you some how see this in the console?
https://github.com/Sec-ant/barcode-detector/blob/bca5f666062e29a8a4d075f71e4695f9e7fc77c1/src/BarcodeDetector.ts#L156-L157
I added this line of code to log a detailed error information, can you some how see this in the console?
https://github.com/Sec-ant/barcode-detector/blob/bca5f666062e29a8a4d075f71e4695f9e7fc77c1/src/BarcodeDetector.ts#L156-L157
The RangeError is what we've been seeking. Is that just an empty object or does it hold more information?
The RangeError is what we've been seeking. Is that just an empty object or does it hold more information?
message:Range consisting of offset and length are out of bounds.
stack:set@[native code]
Hmm, interesting.
If this is something about the WebAssembly instantiation, I wonder why vue-qrcode-reader demo page works.
Does this error message have a context so that I can check which line of code and file this error is thrown from? Or can you jump to the corresponding file and provide some information on its whereabouts? Screenshots would be great, and you can email me if you want.
PS: I previously said
Once the version problem is fixed and released in vue-qrcode-reader, you won't have to worry about downloading it with the matching version. You can just import or copy it from
/node_modules/@sec-ant/zxing-wasm/dist/reader/zxing_reader.wasm.
The good news is, starting from [email protected], this version problem is fixed :).
I isolated a stripped down code from my project that is scannable. But the original project still has Range Error and NotSupportedError.
https://github.com/louie0086/test_Barcode
i used mkcert and http-server -S -C {PATH/TO/CERTIFICATE-FILENAME}.pem -K {PATH/TO/CERTIFICATE-KEY-FILENAME}.pem
https://web.dev/i18n/en/how-to-use-local-https/
with local IP test
Thanks for the repo, but I'm afraid a scannable demo can't provide to too much information on why your original project doesn't work.
What about these questions I previously asked:
Does this error message have a context so that I can check which line of code and file this error is thrown from? Or can you jump to the corresponding file and provide some information on its whereabouts?
RangeError stack here:
https://github.com/louie0086/test_Barcode/blob/5c7a69936a4649c5b860b405b6797ba5aef3456c/public/barcode-detector/dist/es/pure.js#L345-L354
$.HEAP8.set(O, L)
RangeError stack here:
https://github.com/louie0086/test_Barcode/blob/5c7a69936a4649c5b860b405b6797ba5aef3456c/public/barcode-detector/dist/es/pure.js#L345-L354
$.HEAP8.set(O, L)
Thanks, this is very helpful. So the error is thrown from this line from the source code:
https://github.com/Sec-ant/zxing-wasm/blob/8b8df68e781e7524ce96f12276c7a028b2c0c9d6/src/core.ts#L390
I'm not very clear about the root cause but I can try to do some debugging. So this error happens on an iPhone iOS 16.6 Safari Browser, right?
RangeError stack here: https://github.com/louie0086/test_Barcode/blob/5c7a69936a4649c5b860b405b6797ba5aef3456c/public/barcode-detector/dist/es/pure.js#L345-L354
$.HEAP8.set(O, L)Thanks, this is very helpful. So the error is thrown from this line from the source code:
https://github.com/Sec-ant/zxing-wasm/blob/8b8df68e781e7524ce96f12276c7a028b2c0c9d6/src/core.ts#L390
I'm not very clear about the root cause but I can try to do some debugging. So this error happens on an iPhone iOS 16.6 Safari Browser, right?
yes.iPhone 14 Pro Max.
But the demo repo is Okay
Can you log the data, byteLength, bufferPtr and HEAP8 if you can patch the source packages in your project?
You can also directly modify the dist file, like this:
And show me the result?
What's the byteLength of the Int8Array, i.e. zxingInstance.HEAP8.byteLength?
byteLength
i just console at barcode-detector.pure.js
const w = await Bt($, ot.getState().zxingModuleOverrides),
{
data: O,
width: G,
height: j,
data: { byteLength: F },
} = c,
Y = w._malloc(F)
console.log('data:',O)
console.log('byteLength:',F)
console.log('bufferPtr:',Y)
console.log('zxingInstance.HEAP8:',w.HEAP8)
w.HEAP8.set(O, Y)
const N = w.readBarcodesFromPixmap(Y, G, j, m, pe(u), g)
w._free(Y)
I mean, can you also log the byteLength of the HEAP8 object in the console? So I can know the total available memory it holds.
like this (add this line):
console.log('zxingInstance.HEAP8.byteLength:', w.HEAP8.byteLength);
w.HEAP8.byteLength
the result: zxingInstance.HEAP8.byteLength:0
That's some useful info and a good start. Apparently, for some reason, the memory is not successfully allocated, which brings us to this line of code:
https://github.com/louie0086/test_Barcode/blob/5c7a69936a4649c5b860b405b6797ba5aef3456c/public/barcode-detector/dist/es/pure.js#L415-L416
Can you help me check whether J.buffer.byteLength is also zero?
That's some useful info and a good start. Apparently, for some reason, the memory is not successfully allocated, which brings us to this line of code:
https://github.com/louie0086/test_Barcode/blob/5c7a69936a4649c5b860b405b6797ba5aef3456c/public/barcode-detector/dist/es/pure.js#L415-L416
Can you help me check whether
J.buffer.byteLengthis also zero?
https://github.com/louie0086/test_Barcode/blob/master/barcode-detector.pure_4.js#L443
K.buffer undefiend
Hmmm, that means wasmMemory is not initiated.
Can you log n, n.exports and n.exports.qa in this function before the return statement?
https://github.com/louie0086/test_Barcode/blob/2faebca6c2e0ed3626b7ebfa183937b76cc279fe/barcode-detector.pure_4.js#L564-L566
The RangeError is what we've been seeking. Is that just an empty object or does it hold more information?