Unhandled promise rejection: TypeError: Cannot read property 'attachData' of undefined
Hello!
As I run tests for my Angular app, I am encountering this error Unhandled promise rejection: TypeError: Cannot read property 'attachData' of undefined in components that aren't using the barcode scanner component I created using this library.
Here's an example of the error message I am seeing while I run the tests. This is an example where it's occurring in a component that isn't using the barcode scanner.

Any suggestions on how to resolve this? Am I not catching a promise correctly somewhere?
I'm not sure how to help you on that one -- according to the stack trace, someone is calling initializeCamera in your component, which goes to Quagga.start, which.. ends up calling into a frame_grabber that doesn't exist. I'd need to be able to get the parameters start() is being called with, to be able to figure out how you're getting an empty frameGrabber... but on top of that, I think the reason for this, overall, is that you're not expecting start() to be called here, and it is?
@ricocynthia did you find anything further on this?
@ericblade @ricocynthia any progress on this?
Anyone able to make a minimal reproduction case so I can have a look at it? I know absolutely nothing about Angular. :|
I have just been looking at this myself and got the same error, it happens if you call start() outside of the init() callback, if you make sure that start() is only called within the init() callback it works as expected, example code below
Angular Component
import {Component, ElementRef, OnInit} from '@angular/core';
import Quagga from "@ericblade/quagga2";
@Component({
selector: 'app-search-form',
templateUrl: './form.component.html',
styleUrls: ['./form.component.scss']
})
export class FormComponent implements OnInit {
query?: string;
constructor(private elRef: ElementRef) { }
ngOnInit(): void {
if (this.elRef.nativeElement.querySelector('#camera') !== null) {
Quagga.init({
inputStream: {
name: 'live',
type: 'LiveStream',
target: this.elRef.nativeElement.querySelector('#camera'),
},
decoder: {
readers: ['code_128_reader', 'ean_reader'],
},
locate: true,
}, (err) => {
if (err) {
console.log(err);
return;
}
console.log('Initialization finished, Ready to start');
Quagga.start();
Quagga.onDetected((val) => {
console.log(val.codeResult.code)
})
})
}
}
}
The HTML is simply just a div with an ID
<div id="camera"></div>
That seems like a reasonable thing we should guard against, but does it match the OP, here? "in components that aren't using the barcode scanner component"?
i'm wondering if i start throwing there, would whatever OP's problem is become just a documented throw? like, this is where the error is occuring, but is it the root cause of what's happening?
For root cause, Based on what I can see the error is being thrown because the Quagga code can't find the element it trying to attach to, which is the correct behaviour of the code and I'm not convinced that the issue lies with Quagga without actual code examples from the OP
Noting that this is only speculation, only thing I can think of which would cause what the OP is seeing is they start the camera and then the test moves on to other components of Angular, without more information from the OP not much I could comment on the exact nature of the error
But could be fixed of calling ngOnDestory() to stop() the camera when the component changes and the barcode scanner is no longer being used
ngOnDestroy() {
Quagga.stop();
}
There could also be something in the OP's code is trying to restart the camera and could be a simple fix by adding some logic to check if the element exists
if (this.elRef.nativeElement.querySelector('#camera') !== null) { ... }
Again some comments from the OP would help get to the root cause as I have not been able to replicate the issue other than calling start() outside of the init() callback
right, like I'm curious why Angular is causing it to occur in different parts of the code. Even if it's being used correctly, is OP structuring something so that Angular would be calling init() and start() several times unexpectedly?
Either way, though, it sounds like it's probably a good idea to either make start() throw if init() hasn't been completed, and/or if start() receives a configuration block, then do init() and chain to start() when it's done...