fix: ZXing per-frame 'no detection' errors were being treated as camera failures

ZXing's decodeFromVideoDevice fires its callback on every video frame
(~30fps). When no barcode is in view, it passes `(null, err)` where err
is 'No MultiFormat Readers were able to detect the code' — this is
NORMAL, not a hardware failure.

The error branch now filters out 'multiformat' and 'unable to detect'
messages, only calling handleCameraError for real device-level issues
(permission denied, camera not found, stream broken).
This commit is contained in:
2026-06-01 22:56:54 -04:00
parent 6322786fd2
commit 111008a858
+11 -4
View File
@@ -2909,7 +2909,11 @@
} }
}, 5000); }, 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) => { codeReader.decodeFromVideoDevice(deviceId, video, (result, err) => {
// Clear the timeout once we get any callback (stream started or error) // Clear the timeout once we get any callback (stream started or error)
clearTimeout(cameraFailTimer); clearTimeout(cameraFailTimer);
@@ -2919,9 +2923,12 @@
handleBarcode(val.trim()); handleBarcode(val.trim());
} }
} else if (err && scanningActive) { } else if (err && scanningActive) {
// ZXing reports camera errors through the callback (not as exceptions) // Filter out "no barcode in frame" — that's normal, not a failure
console.error('ZXing camera error:', err); const msg = (err.message || err || '').toLowerCase();
handleCameraError(new Error(err.message || err)); if (!msg.includes('multiformat') && !msg.includes('unable to detect')) {
console.error('ZXing camera error:', err);
handleCameraError(new Error(err.message || err));
}
} }
}); });
} catch (e) { } catch (e) {