BackstopJS test execution failing: "Error: Stream not writable"
So I've just started tinkering with BackstopJS. I setup some basic tests and was trying to work it into my normal build process in gulp.
For some reason though, the script just stopped executing correctly. The test worked fine several times earlier today, I came back later, made some CSS changes in my project, ran another test, and received this error:
Bitmap file generation completed.
COMMAND | Executing core for `report`
events.js:141
throw er; // Unhandled 'error' event
^
Error: Stream not writable
at ChunkStream.write (/Users/*****/Sites/*****/node_modules/pngjs/lib/chunkstream.js:46:24)
at PNG.write (/Users/*****/Sites/*****/node_modules/pngjs/lib/png.js:92:16)
at ReadStream.ondata (_stream_readable.js:525:20)
at emitOne (events.js:77:13)
at ReadStream.emit (events.js:169:7)
at readableAddChunk (_stream_readable.js:146:16)
at ReadStream.Readable.push (_stream_readable.js:110:10)
at onread (fs.js:1738:12)
at FSReqWrap.wrapper [as oncomplete] (fs.js:576:17)
For comparison, here is the same output from earlier today:
Bitmap file generation completed.
COMMAND | Executing core for `report`
compare | ERROR { size: isDifferent, content: 40.95%, threshold: 0.1% }: ***** *****_0_document_0_phone.png
See: /Users/*****/Sites/*****/backstop_data/bitmaps_test/20161115-135709/failed_diff_*****_0_document_0_phone.png
compare | OK: ***** *****_0_document_0_phone.png
compare | OK: ***** *****_0_document_0_phone.png
compare | ERROR { size: ok, content: 1.06%, threshold: 0.1% }: ***** *****_0_document_1_tablet_v.png
See: /Users/*****/Sites/*****/backstop_data/bitmaps_test/20161115-135709/failed_diff_*****_0_document_1_tablet_v.png
compare | OK: ***** *****_0_document_1_tablet_v.png
compare | OK: ***** *****_0_document_1_tablet_v.png
compare | ERROR { size: ok, content: 0.60%, threshold: 0.1% }: ***** *****_0_document_2_tablet_h.png
See: /Users/*****/Sites/*****/backstop_data/bitmaps_test/20161115-135709/failed_diff_*****_0_document_2_tablet_h.png
compare | OK: ***** *****_0_document_2_tablet_h.png
compare | OK: ***** *****_0_document_2_tablet_h.png
report |
Test completed...
report | 6 Passed
report | 3 Failed
I tried deleting the html_report directory and rerunning the script. That didn't work. I tried deleting bitmaps_reference and bitmaps_test. It could recreate the images, but the test failed in the same fashion.
There's also nothing fancy about the backstop.json file. I think it's just adapted from one of the demos:
{
"id": "*****",
"viewports": [
{
"name": "phone",
"width": 320,
"height": 480
},
{
"name": "tablet_v",
"width": 568,
"height": 1024
},
{
"name": "tablet_h",
"width": 1024,
"height": 768
}
],
"scenarios": [
{
"label": "*****",
"url": "*****/*****/index.html",
"readyEvent": "backstopjs_ready",
"misMatchThreshold" : 0.1,
"onBeforeScript": "onBefore.js",
"onReadyScript": "onReady.js"
},
{
"label": "*****",
"url": "*****/*****/index.html",
"readyEvent": "backstopjs_ready",
"misMatchThreshold" : 0.1,
"onBeforeScript": "onBefore.js",
"onReadyScript": "onReady.js"
},
{
"label": "*****",
"url": "*****/*****/index.html",
"readyEvent": "backstopjs_ready",
"misMatchThreshold" : 0.1,
"onBeforeScript": "onBefore.js",
"onReadyScript": "onReady.js"
}
],
"paths": {
"bitmaps_reference": "backstop_data/bitmaps_reference",
"bitmaps_test": "backstop_data/bitmaps_test",
"casper_scripts": "backstop_data/casper_scripts",
"html_report": "backstop_data/html_report",
"ci_report": "backstop_data/ci_report"
},
"casperFlags": [],
"engine": "phantomjs",
"report": ["browser"],
"debug": false
}
Does anyone have any ideas?
The error is coming from the pngjs package. Looks like it cant write to the destination.
Stupid question -- You don't literally use * in your filenames right? You're just redacting manually for demo purposes -- correct?
Does this fix itself if you blow away the backstopjs directory and start over?
Yes, the *** is meant to anonymize the client that I'm working on. :)
I deleted the backstop_data directory. I also tried removing it from package.json, running npm prune and then installing everything from scratch, and I'm still getting the exact same error.
I also tried chmod 777 backstop_data just to see if that was the problem. Still nothing.
Please include your full terminal log.
Here's what I am getting (I'm leaving out the full source code because it's extensive):
CasperJS: </body>
CasperJS: [info] [phantom] Step anonymous 88/90: done in 5640ms.
CasperJS: [info] [phantom] Step anonymous 89/90: done in 5658ms.
CasperJS: Capturing screenshots for tablet_h (1024x768)
CasperJS: [debug] [phantom] Capturing page to /Users/*****/Sites/*****/backstop_data/bitmaps_test/20161128-140232/*****_0_document_2_tablet_h.png
CasperJS: [info] [phantom] Capture saved to /Users/*****/Sites/*****/backstop_data/bitmaps_test/20161128-140232/*****_0_document_2_tablet_h.png
CasperJS: [info] [phantom] Step anonymous 90/90: done in 5856ms.
CasperJS: [info] [phantom] Done 90 steps in 5857ms
CasperJS: Comparison config file updated.
CasperJS: [debug] [phantom] Navigation requested: url=about:blank, type=Other, willNavigate=true, isMainFrame=true
CasperJS: [debug] [phantom] url changed to "about:blank"
Bitmap file generation completed.
COMMAND | Executing core for `report`
events.js:141
throw er; // Unhandled 'error' event
^
Error: Stream not writable
at ChunkStream.write (/Users/*****/Sites/*****/node_modules/pngjs/lib/chunkstream.js:46:24)
at PNG.write (/Users/*****/Sites/*****/node_modules/pngjs/lib/png.js:92:16)
at ReadStream.ondata (_stream_readable.js:525:20)
at emitOne (events.js:77:13)
at ReadStream.emit (events.js:169:7)
at readableAddChunk (_stream_readable.js:146:16)
at ReadStream.Readable.push (_stream_readable.js:110:10)
at onread (fs.js:1738:12)
at FSReqWrap.wrapper [as oncomplete] (fs.js:576:17)
Same here
COMMAND | Executing core for `report`
Uncaught exception: Stream not writable Error: Stream not writable
at ChunkStream.write (/usr/local/lib/node_modules/backstopjs/node_modules/node-resemble-js/node_modules/pngjs/lib/chunkstream.js:46:24)
at PNG.write (/usr/local/lib/node_modules/backstopjs/node_modules/node-resemble-js/node_modules/pngjs/lib/png.js:92:16)
at ReadStream.ondata (_stream_readable.js:555:20)
at emitOne (events.js:96:13)
at ReadStream.emit (events.js:188:7)
at readableAddChunk (_stream_readable.js:176:18)
at ReadStream.Readable.push (_stream_readable.js:134:10)
at onread (fs.js:2004:12)
at FSReqWrap.wrapper [as oncomplete] (fs.js:681:17)
/usr/local/lib/node_modules/backstopjs/cli/index.js:57
throw err;
^
Error: Stream not writable
at ChunkStream.write (/usr/local/lib/node_modules/backstopjs/node_modules/node-resemble-js/node_modules/pngjs/lib/chunkstream.js:46:24)
at PNG.write (/usr/local/lib/node_modules/backstopjs/node_modules/node-resemble-js/node_modules/pngjs/lib/png.js:92:16)
at ReadStream.ondata (_stream_readable.js:555:20)
at emitOne (events.js:96:13)
at ReadStream.emit (events.js:188:7)
at readableAddChunk (_stream_readable.js:176:18)
at ReadStream.Readable.push (_stream_readable.js:134:10)
at onread (fs.js:2004:12)
at FSReqWrap.wrapper [as oncomplete] (fs.js:681:17)
Same here on Node v8.9.3 and Backstop v3.0.37
events.js:183
throw er; // Unhandled 'error' event
^
Error: Stream not writable
at module.exports.ChunkStream.write (/Users/xxx/node_modules/node-resemble-js/node_modules/pngjs/lib/chunkstream.js:46:24)
at exports.PNG.PNG.write (/Users/xxx/node_modules/node-resemble-js/node_modules/pngjs/lib/png.js:92:16)
at ReadStream.ondata (_stream_readable.js:639:20)
at emitOne (events.js:116:13)
at ReadStream.emit (events.js:211:7)
at addChunk (_stream_readable.js:263:12)
at readableAddChunk (_stream_readable.js:250:11)
at ReadStream.Readable.push (_stream_readable.js:208:10)
at onread (fs.js:2050:12)
at FSReqWrap.wrapper [as oncomplete] (fs.js:658:17)
Same here. Any update on this?
Node v9.6.1 backstop v3.1.19
compare | OK: About jcsi_test_About_0_document_2_tablet_h.png
events.js:112
throw er; // Unhandled 'error' event
^
Error: Stream not writable
at module.exports.ChunkStream.write (/Users/dellabaines/.nvm/versions/node/v9.6.1/lib/node_modules/backstopjs/node_modules/node-resemble-js/node_modules/pngjs/lib/chunkstream.js:46:24)
at exports.PNG.PNG.write (/Users/dellabaines/.nvm/versions/node/v9.6.1/lib/node_modules/backstopjs/node_modules/node-resemble-js/node_modules/pngjs/lib/png.js:92:16)
at ReadStream.ondata (_stream_readable.js:646:20)
at ReadStream.emit (events.js:127:13)
at addChunk (_stream_readable.js:269:12)
at readableAddChunk (_stream_readable.js:256:11)
at ReadStream.Readable.push (_stream_readable.js:213:10)
at fs.read (fs.js:2123:12)
at FSReqWrap.wrapper [as oncomplete] (fs.js:680:17)
compare | OK: News jcsi_test_News_0_document_0_phone.png
Can you try running the sanity check? https://github.com/garris/BackstopJS#sanity-test-does-backstop-work-in-my-enviornment
Yeah, sanity check worked and after running it I'm no longer seeing the 'Stream not writable error' when running from my project.
Thanks!
I'm getting the same error even though sanity check does work correctly.
I tried debugging it and the last place where code executes correctly is the compare-resemble.js file, up to the line with comparison.onComplete. Callback passed to this method never executes, because of "Stream not writable" happening inside of node-resemble-js.
So, this seems to be a bug in node-resemble-js or even deeper. One thing that might be done on the backstopjs side is to catch such error and handle it somehow. Current behavior is very annoying, because backstop hangs forever during the "report" phase.
Unfortunately, node-resemble-js has no onError method so the only place where backstopjs can recognize that something went wrong, is in core/util/compare/index.js file, in compareImages method. The following code properly rejects a promise if the child comparison process ended with error (ie. because of uncaught "Stream not writable").
worker.on('exit', function (code, signal) {
if (code > 0) {
logger.error('EXECUTION ERROR');
reject('There was an error in child process');
}
});
However, I didn't check what impact this rejection will have on the rest of the code. Good thing is that it doesn't hang with this lines added.
I've traced the error down to the pngjs package that lies below node-resemble-js.
First problem is that node-resemble-js currently uses pngjs@~2.2.0 while 3.4.0 is available. However, this does not fix the issue, only the error thrown changes to Unexpected end of input. Luckily, there is a fix for that ready but waiting for author to merge it into pngjs: https://github.com/lukeapage/pngjs/pull/130
When it gets merged, the dependency of node-resemble-js needs to be changed or maybe npm-shrinkwrap might be used in BackstopJs to enforce newer pngjs.
Still getting the same error. Any news on this? Is there some workaround for this problem? Or is there some reason already known why it is occuring?
Aforementioned bug in pngjs is still there, still not merged. I've also tried to make contact with author of node-resemble-js to take care of this unmaintained library but there was no answer from the author.
https://github.com/lukeapage/pngjs/pull/130 got merged. Unfortunately node-resemble-js remains dead. Efforts to reach its author rendered futile. Any other efforts to merge different versions of resemble forks too. How about taking over the library in te form of own fork?
There seems to be a runtime environment relation to this issue. After updating NodeJs version 8.x -> 12.x this problem disappeared.
here seems to be a runtime environment relation to this issue. After updating NodeJs version 8.x -> 12.x this problem disappeared.
Unfortunately did not disappear completly :( With Node 8.x only ~10% executions succeeded. With Node 12.x ~10% executions fail.
same here. It happened for me consistently in a specific scenario. My workaround was forcing node-resemble dependency of pngjs to 4.0.1 by changing in my package-lock.json from :
"node-resemble-js": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/node-resemble-js/-/node-resemble-js-0.2.0.tgz",
"integrity": "sha1-ijbGZ4ph5dhFX+xYAJsbAnGxkJo=",
"requires": {
"jpeg-js": "0.2.0",
"pngjs": "~2.2.0"
},
"dependencies": {
"pngjs": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/pngjs/-/pngjs-2.2.0.tgz",
"integrity": "sha1-ZJZjYJoOurh8jwiz/nJASLUdnX8="
}
}
},
to:
"node-resemble-js": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/node-resemble-js/-/node-resemble-js-0.2.0.tgz",
"integrity": "sha1-ijbGZ4ph5dhFX+xYAJsbAnGxkJo=",
"requires": {
"jpeg-js": "0.2.0"
},
"dependencies": {
"pngjs": {
"version": "4.0.1"
}
}
},
....
For this new dependency to work, node_modules must be empty, then run npm install and from then on use only npm ci
Also running suddenly into this error with our 200+ images after it was working well for a long time.
It seem that current BS master is using "node-resemble-js": "^0.2.0" which might include a problem, but certainly is outdated.
I added an issue https://github.com/lksv/node-resemble.js/issues/49 to clear things up, but as far as I read above this one is dead.
@garris Maybe there is an option to upgrade to one of the following?
- https://www.npmjs.com/package/node-resemble-v2
- https://www.npmjs.com/package/resemblejs-node
- https://www.npmjs.com/package/resemblejs-papandreou
- https://www.npmjs.com/package/resemblejs (the original without "node")
Hello Folks! Hi @garris,
https://github.com/lksv/node-resemble.js/ maintainer here! Long time no see. Sorry for such late response, last year I've merged a pull request with some version updates but didn't published a new version with tags.
So I've published a new version v1.2.0 on github but I don't think I've access to npm package. What I can suggest is pointing to master instead of old versions and kindly let me know if that helps!
@mirzazeyrek I really prefer to pull in a released version as opposed to reference a tagged version. Does @lksv have access to publish a release?
@digitaldonkey This is regarding https://github.com/lksv/node-resemble.js/issues/49 that you logged.
Hi @mirzazeyrek -- Good to hear from you -- hoping you and your family are in good health!
Are you saying that you made a fix but you can't access the NPM repo? Do you want to simply start your own NPM release fork and have BackstopJS point to that?
@benbcai would this approach resolve your issue?
Hi @garris, I think what @mirzazeyrek is saying is that node-resemble-js v1.2.0 is only tagged in github but it is not published to npm. As you can see here in npmjs, the latest released version is 0.2.0. BackstopJS currently depends on node-resemble-js v0.2.0, which then depends on pngjs v2.2.0. The Stream not writable error reported here is fixed in a newer version of pngjs. node-resemble-js tagged version 1.2.0 is updated to depend on pngjs v6.0.0 which has the fix but node-resemble-js v1.2.0 is not released and we can't use it.
The issue I'm having is actually in terra-toolkit which currently is using node-resemble-js v1.2.0. What I'm requesting is if we can get a released version of resemble-js v1.2.0 so it can use pngjs v6.0.0 instead of referencing the master branch I don't want to do in production code.
@benbcai thank you for explaining. Please let me know if you can get this sorted out. I am happy to bump BackstopJS when the package version is published to npm.
Sadly I didn't get a response from Lukas and I have published a new version on npm:
https://www.npmjs.com/package/@mirzazeyrek/node-resemble-js
Please let me know if this published version works for you ? @benbcai @digitaldonkey @garris
Great! Will do this soon -- thank you @mirzazeyrek.
Thank you @mirzazeyrek for publishing a new release!
Hi @garris when would you be able to bump the version / test the fix?
I have also started getting bitten by this. Is there a known workaround until there's a new release of backstop?
(I tried using npm-force-resolutions, but it doesn't seem to take, probably because the fixed node-resemble-js is actually a new package published under @mirzazeyrek's namespace, rather than just a newer version.)