adaltas/node-csv

Error isn't properly caught or returned when attempting to parse an image

whiterook6 opened this issue · 3 comments

Describe the bug

When attempting to parse a non-CSV, such as a PNG file, an uncaught exception is thrown instead of passing an error to the parse callback, and the caller has no idea that the parsing didn't work.

Uncaught TypeError: Argument must be a Buffer
    equals index.js:577
    bom index.cjs:779
    parse index.cjs:779
    _transform index.cjs:1321
    _read _stream_transform.js:184
    _write _stream_transform.js:172
    doWrite _stream_writable.js:428
    writeOrBuffer _stream_writable.js:417
    write _stream_writable.js:334
    writer index.cjs:1387
    run setImmediate.js:40
    runIfPresent setImmediate.js:69
    onGlobalMessage setImmediate.js:109

Ideally, an error would instead be passed into the callback to parse.

To Reproduce

useEffect(() => {
        if (!inputRef.current) {
            inputRef.current = document.createElement("input");
        }

        const input = inputRef.current;
        input.type = "file";
        input.accept = ".csv";
        input.onchange = () => {
            const files = Array.from(input.files || []);
            if (files.length === 0) {
                return;
            }

            const file = files[0];
            const reader = new FileReader();
            reader.onerror = () => {
                onError(new Error("Failed to read file"));
            };
            reader.onload = (e) => {
                if (!e.target || !e.target.result) {
                    onError(new Error("File is empty or invalid"));
                    return;
                }
                try {
                    parse(e.target.result as string, {columns: true}, (err, data) => { // doesn't even call the callback
                        if (err) {
                            onError(err);
                            return;
                        } else if (!data || !Array.isArray(data) || data.length === 0) {
                            onError(new Error("No data"));
                            return;
                        }

                        onImport(data);
                    });
                } catch (e) {
                    onError(e as Error); // not caught here
                }
            };
            reader.readAsText(file);

            return () => {
                input.onchange = null;
                if (input.parentElement) {
                    input.parentElement.removeChild(input);
                }
            };
        };
    }, []);

Additional context

I'm building a react component that will allow users to click on a button, have it open a file dialog, and try to parse the file that is chosen. It is possible a user might pick an invalid file, but that should result in a detectable, caught error that is passed to the callback.

Could you write me a sample test that reproduce the issue, it makes my life easier.

I tried making a sandbox to recreate the issue, but the problem doesn't occur in the sandbox--that is to say, the error is properly caught. I'm not sure what's different about my setup. https://codesandbox.io/s/gallant-mopsa-plkili

Stepping through my code, I get this error specifically:

Screen Shot 2023-03-24 at 9 46 05 AM

In the sandbox, it skips setImmediate and uses setTimeout instead. That's the only difference I can find.

My code:
Screen Shot 2023-03-24 at 9 49 17 AM

The sandbox:
Screen Shot 2023-03-24 at 9 49 08 AM

I'll understand if you can't reproduce this issue and have to close the ticket. It might be something to do with Buffer instead. Thanks for checking.

Closing after lack of activity.