400 Bad request when uploading a file via GraphQL

System Information
  • Strapi Version: 3.3.4
  • Operating System: MacOS 11.0
  • Database: sqlite
  • Node Version: 14.15.1
  • NPM Version: 6.14.8
  • Yarn Version: 1.22.10

Hello everyone,

While I am quite sure I am missing something crucial here I can’t really figure out what. I’m trying to implement a single file upload. I didn’t set any service to upload to since I want to save it to my file system (perhaps that is the case), or I need to format data I am sending in a different way so the graphql can resolve it.

Either way here is the code:

import React, { useState } from 'react'
import { gql, useMutation } from '@apollo/client'

const UPLOAD_PART_IMAGE = gql`
    mutation($file: Upload!) {
        upload(file: $file) {

function AddPartImage() {

    const [image, setImage] = useState()

    const handleSubmit = (event) => {

    const [addImage] = useMutation(UPLOAD_PART_IMAGE, {
        variables: {
            file: image,

    return (
            <form onSubmit={(event) => {handleSubmit(event)}}>
                <input type="file" name="files" alt="image" onChange={(e) => {setImage(e.target.files[0])}} />
                <button type="submit">Upload</button>

I get following GraphQL error:

If it is not obvious from the example I am trying to upload the file to Strapi via separate React frontend app


Take a look at this gist:

Hei @sunnyson, thanks for the reply

I have actually found this gist and used it to implement it into my functional component. I have now used the identical code in a new class component and I still get the same error → "“Variable “$file” got invalid value {}; Upload value invalid.”

When I hardcode “test string” as a value of the file variable in the mutation, the error says "…got invalid value “test string” so it receives it but it doesn’t receive proper data from the state i.e. it receives { }.

If I console log image from the state before firing mutation I get this:

File {name: "60.jpg", lastModified: 1607588573559, lastModifiedDate: Thu Dec 10 2020 09:22:53 GMT+0100 (Central European Standard Time), webkitRelativePath: "", size: 25900, …}

You probably missed the createUploadLink function in the gist. I made that mistake

I’ve set all of this up, but couldn’t make it work

OMG, it turns out I had this link in my chain, serializing the payload :sweat_smile:

const clearTypeName = new ApolloLink((operation, forward) => {

  if (operation.variables) {

    /* eslint-disable */

    operation.variables = JSON.parse(JSON.stringify(operation.variables), omitTypename);


  return forward(operation).map((data) => {

    return data;



where to implement this variable in the code @Alex_Alonso

Use Altair for File upload because default GQL playground doesnt support that