diff --git a/static/index.html b/static/index.html
index bc620a7..d2b0fd8 100644
--- a/static/index.html
+++ b/static/index.html
@@ -2909,7 +2909,11 @@
}
}, 5000);
- // decodeFromVideoDevice handles camera + scanning in one call
+ // decodeFromVideoDevice handles camera + scanning in one call.
+ // The callback fires on every video frame (~30fps). ZXing passes
+ // "No MultiFormat Readers..." as an error when no barcode is in view
+ // — that's NORMAL, not a hardware failure. Only treat real device
+ // errors (permission denied, camera not found, stream broken) as fatal.
codeReader.decodeFromVideoDevice(deviceId, video, (result, err) => {
// Clear the timeout once we get any callback (stream started or error)
clearTimeout(cameraFailTimer);
@@ -2919,9 +2923,12 @@
handleBarcode(val.trim());
}
} else if (err && scanningActive) {
- // ZXing reports camera errors through the callback (not as exceptions)
- console.error('ZXing camera error:', err);
- handleCameraError(new Error(err.message || err));
+ // Filter out "no barcode in frame" — that's normal, not a failure
+ const msg = (err.message || err || '').toLowerCase();
+ if (!msg.includes('multiformat') && !msg.includes('unable to detect')) {
+ console.error('ZXing camera error:', err);
+ handleCameraError(new Error(err.message || err));
+ }
}
});
} catch (e) {