Greetings,
I am currently developing the backend system for our Shopify store. The main component is a bulk import function based on our own company database. I tried importing this via the Shopify GraphQL API, using Apollo Client.
Upload staging, aswell as file upload works without a problem. Triggering the bulk operation mutation however throws an internal server error on your end.
“GraphQL Error: Error: Internal error. Looks like something went wrong on our end. Request ID: 9f91eafc-e909-42ca-90d1-30551c1fb739 (include this in support requests).”
Can a technician on the team provide any insights or further debugging information? This functionality is front and center of our system.
Some additional info:
-
The JSONL file I am using for tests contains 44 lines
-
I am using an embedded app with Express & React
-
All mutation calls etc. currently happen on the frontend with Apollo
Kind regards,
Christopher Capito
Update: The productCreateMutation does fail on single products, because not all products provide all metafields I defined in the DTO currently. However, as I read, this should not “interfere” with the bulk operation itself.
Is this information correct: If any given amount of operations as part of a bulk operation fail, then I will get an array of error messages upon querying the result of the bulk operation?
As far as I understand, technically all action of this bulk operation could fail, but the bulk operation itself should not produce this error, rather it should return the resulting errors of the actions.
This problem still persists. I fixed a load of issues on the productCreate calls.
I am now doing a test bulk operation with one tested product (single add worked fine). I still get an internal shopify error, without any further debugging information.
This is the returned error ID: 73090304-a027-429a-aec6-0dad239b2f8d
If someone from the team could look this up, I would be mre than grateful
Hey @CCapito - thanks for getting in touch, I understand where you’re coming from here, those generic errors can sometimes not be the most parseable when trying to figure out how to fix an issue. I was able to take a look at the logs on our end and can confirm a few more details on this for you.
It looks like the actual error was related to your query variables being imported as strings rather than as a hash. My understanding is that this relates to the variables within the JSONL file itself. I also am going to advocate for better wording for errors on our end if possible. I can’t guarantee anything, but I’ll do my best to pass along a note to our team as I understand how helpful having less generic error messages would be when it comes to troubleshooting issues like this.
Hope this has provided some next steps for you - happy to keep digging into this if need be.
Hi Alan,
thanks for the information. That already helps me dig into this a little more, which is needed because I am about to add 1000 products hehe.
Variables within the JSON file themselves eh? Maybe you can help me out a bit here (again). I am not using a JSONL File, I am generating the JSONL in memory and storing it in a variable. I am then feeding that into the FileUpload. Is that entirely unsupported?
I am using a pretty simple oneliner to convert by input array of productCreate DTOs into a JSONL string.
export const toJSONL = (input) =>
input.map((x) => JSON.stringify(x)).join("\n");
And this for uploading the actual file
// Upload the file to Shopify
async function handleUploadFile() {
const url =
stagedUploadsCreateObject.data.stagedUploadsCreate.stagedTargets[0].url;
const parameters =
stagedUploadsCreateObject.data.stagedUploadsCreate.stagedTargets[0]
.parameters;
const formData = new FormData();
for (const parameter of parameters) {
const { name, value } = parameter;
formData.append(name, value);
}
formData.append("file", jsonl);
const result = await fetch(url, {
method: "POST",
body: formData,
})
.then((response) => response.text())
.then((data) => {
let parser = new DOMParser(),
xmlDoc = parser.parseFromString(data, "text/xml");
setFileUploadResult(xmlToJson(xmlDoc));
})
.catch((err) => console.log("File Upload Error: ", err));
}
This is just some react code though. The question here really is just how the JSONL should be sent properly. As far as I understood the documents and the content-type, I should be able to attach the JSONL as a raw string of concatenated json objects. Or do I need to actually save a file and regrab it?
I am now trying the following:
const blob = new Blob([jsonl], { type: "text/jsonl"})
const formData = new FormData();
... add all the other parameters
formData.append("file",blob,"products.jsonl");
This however still throws an error, so I presume this did not fix the issue at hand. This is the request id: cb6a1125-40b4-4484-a6f3-9dd4595b284f
It keeps throwing an error regarding an invalid productCreate Input. So the only thing I could think of, is that the JSONL is not being constructed correctly, or has wrong stringification maybe? The inputs work when being used on their own.
@Alan_19 I limited the array to just two JSON lines. I pasted them here: https://www.toptal.com/developers/hastebin/erucirixiy.json
Can you confirm those as valid inputs?
Also, can you confirm this is the correct GraphQL mutation?
export const BULK_OPERATION_RUN = gql`
mutation bulkOperationRunMutation($stagedUploadPath: String!) {
bulkOperationRunMutation(
mutation: "mutation call($input: ProductInput!, $media: [CreateMediaInput!]) { productCreate(input: $input, media: $media) { userErrors { message field } } }"
stagedUploadPath: $stagedUploadPath
) {
bulkOperation {
id
url
status
}
userErrors {
field
message
}
}
}
`;
I am now working around the issue by doing a huge array of promises. However, that is obviously really really slow.