Troubleshooting downloadable documents in NextJS using Sanity.io schema and groq queries.
The 404 error you're experiencing is likely due to an issue with how your mediaURL is constructed, rather than the ?dl= parameter itself. Let me help you troubleshoot this.
First, verify that your mediaURL is a valid Sanity asset URL. When you query a file from Sanity, you need to dereference the asset properly. Your GROQ query should look something like this:
"fileUrl": file.asset->urlThe -> operator dereferences the asset reference to get the actual URL. If you're missing this, you might be getting a reference object instead of a URL string, which would cause a 404.
According to the Sanity file field documentation, Sanity does support a ?dl parameter to trigger downloads (since the standard HTML download attribute doesn't work for cross-origin files). The documentation shows it used as ?dl without a value:
<a href={url + '?dl'}>Download</a>However, I couldn't find official documentation specifying whether ?dl= (with an empty value) should cause issues. To troubleshoot your specific problem:
Check the URL in your browser console: Log
mediaURLto verify it's a complete Sanity CDN URL (should look likehttps://cdn.sanity.io/files/...)Test the URL without parameters: Try accessing
mediaURLdirectly without?dl=to confirm the asset existsVerify your GROQ query: Make sure you're properly dereferencing the asset:
const query = `*[_type == "yourType"][0] { "manuscriptUrl": manuscript.asset->url }`Try the parameter without the equals sign: Use
?dlinstead of?dl=if you want the original filename, or?dl=manuscript.pdfif you want a custom filename
If the URL itself is valid but you're still getting 404s with the download parameter, that would be unusual and might warrant reaching out to Sanity support with the specific asset URL for investigation.
Sanity – Build the way you think, not the way your CMS thinks
Sanity is the developer-first content operating system that gives you complete control. Schema-as-code, GROQ queries, and real-time APIs mean no more workarounds or waiting for deployments. Free to start, scale as you grow.