mafintosh / duplexify

Turn a writable and readable stream into a streams2 duplex stream with support for async initialization and streams1/streams2 input
MIT License
190 stars 36 forks source link

Unhandled 'error' event #39

Open ErlendFax opened 3 years ago

ErlendFax commented 3 years ago

The reason for posting this issue is that It looks like google storage fails and calls this .destroy(...) which throws an unhandled error. I created an issue in the google storage repo.

We were able to reproduce the unhandled error in a test script. We created a simple stream with stream events, pumpify, and duplexify and ran .destroy(error) which threw an unhandled error.

Kinda new to js, node and streams so I don't really understand anything that happens here but tried to debug a bit. When logging inside _destory( ... ) and destroy( ... ) it looks like both of them are called several times, and the internal one is actually called after "finally" has been logged. Does this make sense? Why does this crash?

Script to reproduce error

import * as streamEvents from "stream-events";
const pumpify = require('pumpify');
import {Duplex, PassThrough} from 'stream';
const hashStreamValidation = require('hash-stream-validation');
const duplexify: any = require('duplexify');

class RequestError extends Error {
    code?: string;
    errors?: Error[];
}

function test() {
    let crc32c = true;
    let md5 = false;

    const validateStream = hashStreamValidation({
        crc32c,
        md5,
        });

    const fileWriteStream = duplexify();
    const stream = streamEvents(
        pumpify([
            new PassThrough(),
            validateStream,
            fileWriteStream,
        ])
    ) as Duplex;

    let code;
    let message;

    code = 'FILE_NO_UPLOAD';
    message = 'File upload failed.';
    const error = new RequestError(message);
    error.code = code;
    error.errors = [];
    try {
        fileWriteStream.destroy(error); <-- Crashes
        // fileWriteStream.destroy(); <-- Good
    } catch (err) {
        console.log("fileWriteStream: ", err)
    }
    stream.uncork();
}

try {
    test();
} catch (err) {
    console.log("test: ", err);
} finally {
    console.log("finally");
}

Environment

MacOS: 11.6 Duplexify: 4.1.2 Pumpify: 2.0.1 Hash-stream-validation: 0.2.4 Stream events: 1.0.5 Npm: 6.14.22 Node: 12.22.1

mafintosh commented 3 years ago

I dont write typescript which I presume this is, but you need to error handle your streams by setting up an error handler in general.