Closed facultymatt closed 10 years ago
I am confused why the error is being raised from grunt-contrib-compass
. Is this error being raised when you run grunt sprite
by itself? What happens when you don't load any other grunt tasks?
That did seem odd to me at first. Then I removed compass a grunt task, the error was thrown by: .../node_modules/grunt-google-cdn/node_modules/bower/node_modules/tmp/lib/tmp.js:261
So in both cases the error is thrown by the tmp
module. This is the code around line 261:
process.addListener('uncaughtException', function _uncaughtExceptionThrown( err ) {
_uncaughtException = true;
_garbageCollector();
throw err;
});
Moving on to the actual error, which is thrown by /node_modules/grunt-spritesmith/node_modules/spritesmith/node_modules/phantomjssmith/lib/exporters.js:85:32
this is line 85: var decodedPixels = JSON.parse(encodedPixels);
Meaning the error is coming from attempting to parse json.
I've played around with the image src folder, limiting the images in different ways, i'm wondering if the following factors are breaking it.
Yea, there could be a large variety of things going wrong. Can you clone the phantomjssmith
repo and run the tests?
git clone https://github.com/twolfson/phantomjssmith
cd phantomjssmith
npm install
npm test
Getting 5 tests complete (7 seconds)
.
We should make a point to fix that JSON.parse
to be more graceful in telling us what the message is.
var decodedPixels;
try {
decodedPixels = JSON.parse(encodedPixels);
} catch (e) {
cb(new Error('Error while parsing JSON "' + encodedPixels + '".\n' + e.message));
}
Interesting, can you run npm ls
inside of your repo? I want to confirm that you are running the latest version of grunt-spritesmith
and phantomjssmith
.
Interesting, thats a bit more helpful
../../../../../../../../app/images/icons/ls_arm_overlay.png%22%7D,%22x%22:0,%22y%22:14739%7D%5D,%22options%22:%7B%22format%22:%22png%22,%22quality%22:90%7D%7D:40
null
".
Unexpected token o
not sure where that null is coming from...
Tree is:
├─┬ grunt-spritesmith@1.12.0
│ ├─┬ json2css@4.1.0
│ │ ├── json-content-demux@0.1.3
│ │ └── mustache@0.7.3
│ ├─┬ spritesmith@0.12.1
│ │ ├── async@0.2.9
│ │ ├─┬ layout@1.3.1
│ │ │ └── binpacking@0.0.1
│ │ └─┬ phantomjssmith@0.2.3
│ │ ├─┬ ndarray@1.0.8
│ │ │ └── iota-array@0.0.1
│ │ ├── obj-extend@0.1.0
│ │ ├─┬ save-pixels@0.3.0
│ │ │ ├── pngjs@0.4.0
│ │ │ └── through@2.3.4
│ │ ├── shell-quote@1.4.0
│ │ ├─┬ temporary@0.0.5
│ │ │ └── package@1.0.1
│ │ └── which@1.0.5
│ ├── underscore@1.4.4
│ └── url2@1.0.0
I am not sure that is what I would expect from encodedPixels
. Is there anything else before the ../../...
?
Yes, theres a couple hundred lines. Basically its a url string that starts with file:///Users/facultymatt/Sites/projectName/node_modules/grunt-spritesmith/node_modules/spritesmith/node_modules/phantomjssmith/lib/scripts/compose.html?%7B%22width%22:17149,%22height%22:15258,%22images%22:%5B%7B%22img%22:%7B%22height%22:7,%22width%22:7,%22_filepath%22:%22app/images/icons/bullet.png%22,%22_urlpath%22:
and continues for each image.
Ah, k. There is probably a complaint from PhantomJS somewhere in there. Can you run grunt-spritesmith
with exactly one image?
sprite: {
src: ['app/images/icons/bullet.png'],
...
}
Works fine. I can't tell if I have a corrupt image, or just too many.
Could phantomJS be timing out?
I think this might have something to do with
// Convert over all image paths to url paths
var images = that.images;
images.forEach(function getUrlPath (img) {
img = img.img;
img._urlpath = path.relative(__dirname + '/scripts', img._filepath);
});
not building the path correctly...
Can we try doing a binary search on this?
var images = grunt.file.expand('app/images/icons/*.png');
var len = images.length;
sprite: {
// Adjust offset until we find the failing image
src: images.slice(0, Math.floor(len / 2));
// src: images.slice(Math.floor(len / 2), len));
}
OK, seems the magic number if 246 images. 247 and the process fails. Doesn't seem to matter which images they are - I deleted all images except the magic 246, then duplicated just one of these "valid images" and the process failed. Any ideas?
Could this be an issue with the length of the url here:
var page = webpage.create();
page.open(phantom.libraryPath + '/compose.html?' + encodedArg, function (status) {
// Pluck out the data png
var retStr = page.evaluate(function () {
return window.retStr;
});
// Export the pixel values
console.log(retStr);
// Leave the program
phantom.exit();
});
encodedArg
is created from the images object, stringified and url encoded. In the case of 247 images (the failing number) encodedArg
is 71663 characters long! Maybe this is just too long for a url?
Could we switch this to POST? That would avoid url limitations for length.
Got it! The url is too large. I copied the file:// url into my browser (had to switch to localhost) and got the following message:
Request-URI Too Large
The requested URL's length exceeds the capacity limit for this server.
And the following message in the console:
"NetworkError: 414 Request-URI Too Large - http://localhost:8888/.......really long string!!!..."
So this appears to be a limitation of https://github.com/twolfson/phantomjssmith. I'll open up a ticket there. As for this library it would be worth noting that large sets of images are incompatible with phantom engine, and maybe checking the length of encodedArg
in some place for length.
Great catch! I actually ran into this bug during a hackathon 2 weekends ago but I rushed passed documenting it.
I will document the fix in that ticket you opened up.
The patch inside of phantomjssmith@0.3.0
has been released in grunt-spritesmith@1.13.0
.
Thanks for the quick fix on this!
Getting the following error running the example config (with my proper paths setup of course):