Unable to create media attachment from Buffer
See original GitHub issueHi again, thanks for all your work on this library!
I seem to be getting odd errors when creating media attachments from a Buffer
. This works:
const { id } = await masto.mediaAttachments.create({
file: createReadStream("test.jpg")
});
however, this:
const { id } = await masto.mediaAttachments.create({
file: readFileSync("test.jpg")
});
fails with this output:
undefined:1
SyntaxError: Unexpected end of JSON input
at JSON.parse (<anonymous>)
at SerializerImpl.deserialize (<repo>/node_modules/masto/dist/index.js:3173:43)
at transformResponse (<repo>/node_modules/masto/dist/index.js:3295:41)
at transform (<repo>/node_modules/axios/lib/core/transformData.js:16:12)
at Object.forEach (<repo>/node_modules/axios/lib/utils.js:247:10)
at transformData (<repo>/node_modules/axios/lib/core/transformData.js:15:9)
at onAdapterRejection (<repo>/node_modules/axios/lib/core/dispatchRequest.js:69:32)
form-data
(and by extension isomorphic-form-data
) should accept Buffer
s, as noted in their readmes. The error seems like it might be in masto.js code?
It’s not a big deal for the above example (createReadStream
is probably preferable to reading the whole file in from memory anyway) but for other cases (for example, creating image data in-memory using node-canvas
or similar) it’s a bit inconvenient to have to write a file to a temporary location and then read it back rather than using a Buffer
directly.
Edit: looked into this a bit – it seems like the deserializer is trying to JSON.parse
an empty string (length === 0
). If I make the deserializer return an empty object in this case, I get this output instead:
node_modules/masto/dist/index.js:199
var _this = _super.call(this) || this;
^
Error: Unexpected error occurred
at new MastoError (<repo>/node_modules/masto/dist/index.js:199:28)
at HttpAxiosImpl.<anonymous> (<repo>/node_modules/masto/dist/index.js:3345:39)
at step (<repo>/node_modules/masto/dist/index.js:130:23)
at Object.throw (<repo>/node_modules/masto/dist/index.js:111:53)
at rejected (<repo>/node_modules/masto/dist/index.js:102:65)
at processTicksAndRejections (node:internal/process/task_queues:96:5) {
statusCode: undefined,
description: undefined,
details: undefined,
isMastoError: true
}
If I add logging here, I can finally see that this is a status code 400. (It might be nice to add the status code to the default
case and the request URL too, it’s kinda confusing without it and makes it seem like an internal error…)
I’m still not sure why using a Buffer
isn’t working here, but I’ll keep investigating.
Issue Analytics
- State:
- Created 2 years ago
- Comments:8 (4 by maintainers)
@eramdam You would need to change tsconfig.json as follows since the sub-package is served by a feature called package exports which was introduced in Node.js 16+.
Or if you want to stay in
"moduleResolution": node
for some reason, you can create the following declaration file to yoursrc/global.d.ts
or anywhere you want.Update: @danielroe has added backward compatibility to the
masto/fetch
’s type definition in #761 so you don’t need to updatecompilerOptions.moduleResoltuion
.Here’s an update from #631 #626 . Even though I still could not figure out which component (including form-data, Axios, or Mastodon itself) was causing this bug, I tried out the Node.js-native implementation of Fetch API and everything worked OK.
Node.js’s fetch API has just been introduced at v18.X.X so I still have to maintain the Axios version for a while, but I’m going to drop the Axios version in the future. If you are still in trouble or want to try out the new version, you can install the Fetch API version with the following command:
And change your import to following
Additionally, since it’s Fetch API, you need to convert the buffer to a blob. you can basically do that just by passing the buffer to the blob constructor.