Shopify Processing Error On File Upload Through JS/GraphQL

Topic summary

Issue: Users are experiencing a “Processing error” when uploading images to Shopify via JavaScript and GraphQL. Despite receiving a 200 status response and a valid resourceUrl, uploaded files fail to process and appear with errors in the Shopify Files admin panel. The data.data.node.image returns null because the image hasn’t successfully uploaded.

Attempted Solutions:

  • Tested multiple image formats (PNG, JPG) with small file sizes
  • Verified access token validity
  • Checked parameter order in FormData (file appended last)
  • Confirmed zero userErrors in both stagedUploadsCreate and fileCreate mutation responses

Code Pattern: The implementation uses a two-step process:

  1. stagedUploadsCreate mutation to get upload parameters
  2. POST request with FormData to the staged URL
  3. fileCreate mutation to register the file in Shopify

Current Status: Multiple users report the identical issue with no confirmed resolution. Screenshots show successful API responses but processing failures in Shopify admin. The root cause remains unidentified despite following Shopify’s documented upload workflow.

Summarized with AI on November 5. AI used: claude-sonnet-4-5-20250929.

0

I am implementing a simple solution that allows the user to select a file (any type of image). Once selected, the user clicks on “Upload Image,” and the API call is triggered. I am receiving a status 200 in response, but when I check the Shopify Files directory in the admin panel, it shows me a “Processing error.” As you can see in the screenshot, the resourceUrl is generated correctly. I am also facing an issue in fetching the image; this is because the image has not been uploaded to Shopify, which is why the data.data.node.image is null. Please review the JavaScript code below and let me know the possible reasons that could be causing this Processing error.

I have tried to upload different image types png,jpg with small size but still same issue.

<h1>Upload Image</h1>
<input type="file" id="file-input">
<button id="upload-button">Upload Image</button>

<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script>

const adminApiUrl = 'GRAPHQL_URL';

document.getElementById('upload-button').addEventListener('click', async () => {
    const fileInput = document.getElementById('file-input');
    const selectedFile = fileInput.files[0];
    
    if (selectedFile) {
        // const fileSize = selectedFile.size.toString();
        const file = selectedFile.name;
        try {
            console.error('selectedFile', selectedFile);

            const stagedUploadsQuery = `mutation stagedUploadsCreate($input: [StagedUploadInput!]!) {
              stagedUploadsCreate(input: $input) {
                stagedTargets {
                  resourceUrl
                  url
                  parameters {
                    name
                    value
                  }
                }
                userErrors {
                  field
                  message
                }
              }
            }`;

            // Variables
            const stagedUploadsVariables = {
                input: {
                    resource: 'FILE',
                    filename: selectedFile.name,
                    mimeType: selectedFile.type,
                    fileSize: selectedFile.size.toString(),
                    httpMethod: 'POST',
                },
            };

            const stagedUploadsQueryResult = await axios.post(
                adminApiUrl, {
                    query: stagedUploadsQuery,
                    variables: stagedUploadsVariables,
                }, {
                    headers: {
                        "X-Shopify-Access-Token": 'ACCESS_TOKEN',
                    },
                }
            );
            const target = stagedUploadsQueryResult.data.data.stagedUploadsCreate.stagedTargets[0];
            const url = target.url;
            const resourceUrl = target.resourceUrl;
            const params = target.parameters;
            await performFileCreateTest(target.resourceUrl);
            console.log("resourceUrl", resourceUrl);
          
            const formData = new FormData();
            params.forEach(({ name, value }) => {
              formData.append(name, value);
            });
            formData.append("file", selectedFile);
            await axios.post(url, formData);
          
            alert('Image uploaded successfully!');
        } catch (error) {
            console.error('Error uploading image:', error);
            alert('Error uploading image. Please try again.');
        }
    } else {
        alert('Please select an image to upload.');
    }
});

async function performFileCreateTest(resourceUrl) {

    // Query
    const createFileQuery = `mutation fileCreate($files: [FileCreateInput!]!) {
      fileCreate(files: $files) {
          files {
              fileStatus
              ... on MediaImage {
                  id
              }
          }
          userErrors {
              field
              message
          }
      }
    }`;

    // Variables
    const createFileVariables = {
        files: {
            alt: "alt-tag",
            contentType: "IMAGE",
            originalSource: resourceUrl, 
        },
    };

    // Finally post the file to shopify. It should appear in Settings > Files.
    const createFileQueryResult = await axios.post(
        adminApiUrl, {
            query: createFileQuery,
            variables: createFileVariables,
        }, {
            headers: {
                "X-Shopify-Access-Token": `ACCESS_TOKEN`,
            },
        }
    );
    console.log("createFileQueryResult",createFileQueryResult.data.data.fileCreate.files[0].id);    
    const imageId = createFileQueryResult.data.data.fileCreate.files[0].id;
    await fetchImage(imageId);
}

const fetchImage = async (imageId) => {
  const query = `
    query getFileByID($imageId: ID!) {
      node(id: $imageId) {
        ... on MediaImage {
          id
          image {
            url
          }
        }
      }
    }
  `;

  const variables = { imageId };

  try {
    const response = await axios({
      url: adminApiUrl,
      method: 'post',
      headers: {
        'X-Shopify-Access-Token': 'ACCESS_TOKEN', 
      },
      data: {
        query: query,
        variables: variables,
      },
    });

    const image = response;
    console.log('Image originalSrc:', image);
    //console.log('Image transformedSrc:', image.transformedSrc);
    // You can now use the image URL as needed in your application
  } catch (error) {
    console.error('Error fetching image:', error);
    // Handle errors appropriately in your application
  }
};  
</script>

Hi Ma123456,

Here are a few suggestions that could help troubleshoot the issue:

  1. Check your Access Token: Ensure that the ‘ACCESS_TOKEN’ you’re using in your ‘X-Shopify-Access-Token’ header is valid. Any issues with the access token could lead to a processing error.

  2. Check the Order of Your Parameters: When constructing your ‘formData’ object, the order in which you append the parameters matters. The ‘file’ parameter should be the last one to be appended. If you are appending ‘file’ before any other parameters, Shopify may not be able to process the file.

  3. Check the Response of the ‘fileCreate’ Mutation: You are logging the ‘id’ of the created file, but not the eventual response of the ‘fileCreate’ mutation. There might be user errors in the response that could provide a clue as to why the file is not being processed.

  4. Check for any Errors returned by the ‘stagedUploadsCreate’ mutation: The ‘stagedUploadsCreate’ mutation may return user errors that could indicate why the file isn’t uploading correctly. Make sure to log and check these errors.

I hope these help you debug and solve your issue. Good luck!

**stagedUploadsQueryResult**
![stagedUploadsQueryResult.png|1889x406](upload://8jw3QxNtEY24VORcqTXF0Kf8oY6.png)
**createFileQueryResult**
![createFileQueryResult.png|1893x429](upload://m62olVoHwmL7zKbt1VT5k5aBjTY.png)

For suggestion 3 and 4 please check both responses. There are 0 userErrors.
For suggestion 2, i am already appending data in the last before making post axios call so not sure what you are trying to say here.
For suggestion 1, already checked and i am using the right access token from my private app.

Hello, have you got a solution? because I had the same issue when I tried to upload the image below I have attached my full code.

import React, { useCallback, useEffect, useState, useRef } from "react";
import { json } from "@remix-run/node";
import { useActionData, useNavigation, useSubmit } from "@remix-run/react";
import {
  Page,
  Layout,
  Card,
  Button,
  BlockStack,
  Box,
  InlineStack,
  DropZone,
  LegacyStack,
  Thumbnail,
  Text,
} from "@shopify/polaris";
import { authenticate } from "../shopify.server";
import type { ActionFunctionArgs, LoaderFunctionArgs } from "@remix-run/node";

export const loader = async ({ request }: LoaderFunctionArgs) => {
    await authenticate.admin(request);

    return null;
};

export const action = async ({ request }: ActionFunctionArgs) => {
    const { admin } = await authenticate.admin(request);

    const requestBody = await request.text();

    const formData = new URLSearchParams(requestBody);
    const name = formData.get("filename");
    const type = formData.get("filetype");
    const size = formData.get("filesize");
    const files = [
        {
            name: name,
            type: type,
            size: size,
        },
    ];

    const prepareFiles = (files: { name: string | null; type: string | null; size: string | null; }[]) =>
        files.map((file) => ({
            filename: file.name,
            mimeType: file.type,
            resource: file.type?.includes("image") ? "IMAGE" : "FILE",
            fileSize: file.size?.toString(),
            httpMethod: "PUT",
        }));

    const preparedFiles = prepareFiles(files);

    const uploadFileResponse = await admin.graphql(
        `#graphql
        mutation stagedUploadsCreate($input: [StagedUploadInput!]!) {
        stagedUploadsCreate(input: $input) {
            stagedTargets {
            resourceUrl
            url
            parameters {
                name
                value
            }
            }
            userErrors {
            field
            message
            }
        }
        }
    `,
        { variables: { input: preparedFiles } },
    );

    const uplodeFileJson = await uploadFileResponse.json();

    const resourceurl = uplodeFileJson.data.stagedUploadsCreate.stagedTargets[0].resourceUrl;

    const fileCreateResponse = await admin.graphql(
        `#graphql
        mutation fileCreate($files: [FileCreateInput!]!) {
            fileCreate(files: $files) {
                files {
                    alt
                    createdAt
                    fileErrors {
                        code
                        details
                        message
                    }
                    fileStatus
                    preview {
                        image {
                        url
                        }
                        status
                    }
                }
                userErrors {
                    field
                    message
                }
            }
        }`,
        {
            variables: {
                files: {
                    alt: "Image",
                    contentType: "IMAGE",
                    originalSource: resourceurl,
                },
            },
        },
    );

    const fileCreateJson = await fileCreateResponse.json();

    return json({
        stagedUpload: uplodeFileJson,
        fileCreate: fileCreateJson,
        resourceurl: resourceurl,
        prepareFiles: prepareFiles
    });
};

export default function Index() {
    const nav = useNavigation();
    const actionData = useActionData();
    const submit = useSubmit();
    const isLoading = ["loading", "submitting"].includes(nav.state) && nav.formMethod === "POST";

    useEffect(() => {
        if (actionData) {
        shopify.toast.show("Product created");
        }
    }, [actionData]);

    const [files, setFiles] = useState

Im having the same issue, where you able to solve it?