GraphQL Multipart Request Hangs - BadRequestError: Invalid type for the 'operations' multipart field

61 views Asked by At

I'm encountering an issue in my Node.js application where GraphQL multipart requests, specifically those involving image uploads, result in the application hanging indefinitely. There is no response, and the GraphQL client just shows "loading."

Error Message:

BadRequestError: Invalid type for the 'operations' multipart field (https://github.com/jaydenseric/graphql-multipart-request-spec). This error occurs intermittently, and I suspect it may be related to how the graphql-upload library is handling multipart requests.

I'm using Apollo GraphQL Sandbox to test queries and mutations

Below is a simplified version of my GraphQL mutation and the relevant parts of my server-side code:

    # GraphQL Mutation
    mutation ($createOrderInput: CreateOrderInput!) {
      createOrder(createOrderInput: $createOrderInput) {
        email
        instructions
        orderType
        images {
          imageUrl
          instructions
        }
      }
    } 
    # Variables
    {
      "createOrderInput": {
        "email": "[email protected]",
        "instructions": "test",
        "orderType": "TEST_ORDER",
        "images": [
          {
            "file": null,  //Using apollo Graphql Client to upload image with key: file
            "instructions": "test1"
          }
        ]
      }
    } 
    //Create Order Mutation
    
    // Using graphql-upload-ts to handle file uploads
    
    `import { GraphQLUpload, Upload } from "graphql-upload-ts";`
    
    `interface OrderArgs {`
    `email: string;`
    `instructions: string;`
    `orderType: string;`
    `images: ImageInput[];`
    `}`
    
    `interface ImageInput {`
    `file: Upload;`
    `instructions: string;`
    `}`
    
    `Upload: GraphQLUpload,`
    
    `createOrder: async (_root: any, { email, instructions, orderType, images }: OrderArgs) => {`
    
    `console.log('Inputs: ', email, instructions, orderType, images) // Doesn't log anything.`
    
          try {
            // Fetch user based on the provided email
            const user = await User.findOne({ email });
            if (!user) {
              throw new ApolloError('User not found with provided email', 'USER_NOT_FOUND');
            }
    
    // Check if there are multiple images with instructions
    const hasMultipleImages = images.length \> 1;
    
    // If there are multiple images, use them; otherwise, use a single image
    const imageInfos = hasMultipleImages
    ? await Promise.all(images.map(async (image) =\> {
    const imageUrl = await imageUpload(image.file);
    return { imageUrl, instructions: image.instructions };
    }))
    : \[{
    imageUrl: await imageUpload(images\[0\].file),
    instructions: images\[0\].instructions,
    }\];
    const newOrder = new Order({
    email,
    orderType,
    instructions,
    images: imageInfos,
    });
    
            const savedOrder = await newOrder.save();
            return savedOrder;
          } catch (error) {
            console.error('Error while creating order:', error);
            throw error;
          }
        },`
    
    ImgKitUpload:
    
    const imageUpload = async (file: any) =\> {try {const { createReadStream, filename, mimetype } = await file;console.log('File Mimetype:', mimetype);
    
    // Check if the file is an image (you can extend the list of allowed mimetypes)
    const allowedImageTypes = \['image/jpeg', 'image/png', 'image/gif', 'image/jpg', 'image/webp'\];
    if (!allowedImageTypes.includes(mimetype)) {
    throw new Error('Invalid file type. Only image uploads are allowed.');
    }
    
    const stream = createReadStream();
    
    // Handle the file stream as needed, e.g., upload to ImageKit.io
    const response = await imagekit.upload({
    file: stream,
    fileName: filename,
    // Add other relevant parameters for ImageKit.io
    });
    
    // Return the URL or any other relevant information
    return response.url;
    
    } catch (error) {console.error('Error uploading image:', error);throw new Error('Error uploading       image');}}; 

server.ts:

    const server = new ApolloServer({typeDefs,resolvers,
    })
    await server.start()
    app.use(graphqlUploadExpress());
    server.applyMiddleware({ app, path: '/graphql' }); 

Additional Details:

The GraphQL client keeps showing "loading," and there is no response from the server.

I've observed this behavior specifically when attempting to upload images using a GraphQL multipart request.

The BadRequestError mentioned occurs sporadically, and it seems to be related to the type of the 'operations' multipart field.

Has anyone encountered a similar issue where GraphQL multipart requests cause the application to hang indefinitely, and the BadRequestError is generated? Any insights into what might be causing this behavior would be greatly appreciated.

Environment:

Node.js version: [20.10.0] graphql-upload-ts: [2.1.0],

Tried using only single image upload. That works without any errors. It sends image to imgkit and returns url and stores in db. but with the above code, when i upload a single or multiple image it just keeps loading and doesnt return anything. Even the console.log statements are not logging anything.

0

There are 0 answers