Jules
Jules2mo ago

Error: `r.stream(...).pipe` is not a function when calling `storage.store(...)`

I'm trying to set up Convex Storage, but I'm running into the following error:
TypeError: r.stream(...).pipe is not a function
TypeError: r.stream(...).pipe is not a function
Code:
const { buffer, mimeType } = extractFromDataUrl(dataUrl);
const dataBlob = new Blob([buffer], { type: mimeType });
const storageId = await ctx.storage.store(dataBlob);
const { buffer, mimeType } = extractFromDataUrl(dataUrl);
const dataBlob = new Blob([buffer], { type: mimeType });
const storageId = await ctx.storage.store(dataBlob);
The error is triggered on the line that calls await ctx.storage.store(dataBlob) Has anyone seen this before, or know what could be causing this?
4 Replies
Convex Bot
Convex Bot2mo ago
Thanks for posting in <#1088161997662724167>. Reminder: If you have a Convex Pro account, use the Convex Dashboard to file support tickets. - Provide context: What are you trying to achieve, what is the end-user interaction, what are you seeing? (full error message, command output, etc.) - Use search.convex.dev to search Docs, Stack, and Discord all at once. - Additionally, you can post your questions in the Convex Community's <#1228095053885476985> channel to receive a response from AI. - Avoid tagging staff unless specifically instructed. Thank you!
ian
ian2mo ago
I'd try to inspect what the type of buffer is, and whether it needs to be coerced to something like an ArrayBuffer? maybe try
buffer.slice(
dataOrUrl.byteOffset,
dataOrUrl.byteOffset + dataOrUrl.byteLength
)
buffer.slice(
dataOrUrl.byteOffset,
dataOrUrl.byteOffset + dataOrUrl.byteLength
)
Jules
JulesOP2mo ago
Managed to get it working! For some reason this was caused by the code being inside a "use node" module. By separating it out into a dedicated module without the node directive the error doesn't appear anymore This is the code inside extractFromDataUrl:
const dataUrlRegex = /^data:([^;,]+)(?:;charset=[^;,]*)?(?:;(base64))?,(.*)$/;

function extractFromDataUrl(dataUrl: string): { buffer: ArrayBuffer; mimeType: string } {
const matches = dataUrl.match(dataUrlRegex);

if (!matches) {
throw new Error("Invalid Data URL");
}

const mimeType = matches[1] || "text/plain";
const isBase64 = !!matches[2];
const dataPart = matches[3];

const byteString = isBase64 ? atob(dataPart) : decodeURIComponent(dataPart);

const buffer = new ArrayBuffer(byteString.length);
const view = new Uint8Array(buffer);

for (let i = 0; i < byteString.length; i++) {
view[i] = byteString.charCodeAt(i);
}

return { buffer, mimeType };
}
const dataUrlRegex = /^data:([^;,]+)(?:;charset=[^;,]*)?(?:;(base64))?,(.*)$/;

function extractFromDataUrl(dataUrl: string): { buffer: ArrayBuffer; mimeType: string } {
const matches = dataUrl.match(dataUrlRegex);

if (!matches) {
throw new Error("Invalid Data URL");
}

const mimeType = matches[1] || "text/plain";
const isBase64 = !!matches[2];
const dataPart = matches[3];

const byteString = isBase64 ? atob(dataPart) : decodeURIComponent(dataPart);

const buffer = new ArrayBuffer(byteString.length);
const view = new Uint8Array(buffer);

for (let i = 0; i < byteString.length; i++) {
view[i] = byteString.charCodeAt(i);
}

return { buffer, mimeType };
}
Could it be that using a node environment causes a different ArrayBuffer class to be used?
ian
ian2mo ago
but what's the deal with view - doesn't look like it's returned? Is view.buffer what you want?

Did you find this page helpful?