Slack → Google Drive file uploads ‘hydrate|||…’ text instead of real file—works in testing and on replays, fails on live runs
Hey folks, this has been driving me crazy for the past two days and I’m hoping someone has an idea:I’m running into a frustrating inconsistency with Zapier’s Slack → Google Drive integration.
I have a Zap triggered by “New File in Slack”.
In test mode, everything works perfectly: I can pass the file (exists but not shown) object from Slack directly into the Google Drive upload step and the file uploads correctly.
But in live runs, the same setup mostly fails: instead of uploading the actual file, Google Drive receives a .txt file containing raw text like hydrate|||...|||hydrate
When I replay a live run, without making any changes to the Zap, it then does the correct thing, i.e., uploading the actual file to GDrive
Anyone have any idea what’s going on here, know of a workaround?
Page 1 / 1
Hi @DennisWF
For us to have more info, post screenshots showing:
how your Zap steps are outlined
how your Zap steps are configured in EDIT mode with the field mappings visible in the CONFIGURE tab
The Upload File to Google Drive action. Nothing is being done to the `File (exists but not shown) ` object in between the trigger and this action.
A Google Drive folder ID is being pulled from a Zapier Table in an intermediate step, but that’s not relevant to the issue I’m experiencing; during both live runs and test runs / replays, the file always uploads to the correct folder. It’s just that during live runs, I get the hydrated .txt file, whereas during test runs / replays, I get the actual file.
Also attaching the JSON export in case you want to see it, and a screenshot of the entire Zap, with the relevant sections highlighted.
The most puzzling aspect of this is the divergent behavior between live runs and test runs / replays. Have you experienced a difference in file hydration behavior between these scenarios?
{"metadata":{"version":2},"zaps":[{"id":1,"title":"Upload Files Shared in Slack to Google Drive","nodes":{"1":{"id":1,"paused":false,"type_of":"read","params":{"channel":null,"shared_file":true},"meta":{"$editor":{"has_automatic_issues":false},"timezone":"Asia/Singapore","parammap":{}},"triple_stores":{"copied_from":null,"created_by":null,"polling_interval_override":0,"block_and_release_limit_override":0,"spread_tasks":1},"parent_id":null,"root_id":null,"action":"file","selected_api":"SlackCLIAPI@1.23.0","title":"Upload Files Shared in Slack to Google Drive","authentication_id":"67b798c633cf1a4a4b25a860ef1d5eacfd0bdb0a08f95a3fbc4eaa99e06f19b6"},"2":{"id":2,"paused":true,"type_of":"write","params":{"delay_for_unit":"minutes","delay_for_value":"2"},"meta":{"$editor":{"has_automatic_issues":true},"parammap":{}},"triple_stores":{"copied_from":null,"created_by":null,"polling_interval_override":0,"block_and_release_limit_override":0,"spread_tasks":1},"parent_id":1,"root_id":1,"action":"delay_for","selected_api":"DelayCLIAPI@1.0.4","title":null,"authentication_id":null},"3":{"id":3,"paused":true,"type_of":"filter","params":{"filter_criteria":[{"id":1168988513553461,"group":2991796327503786,"key":"1__channels","value":"","match":"iexist","action":"continue"},{"id":7948485725783828,"group":2991796327503786,"key":"1__mimetype","value":"application/vnd.slack-docs","match":"iexact","action":"stop"}]},"meta":{"$editor":{"has_automatic_issues":false},"stepTitle":"Only Continue if Channel ID Exists"},"triple_stores":{"copied_from":null,"created_by":null,"polling_interval_override":0,"block_and_release_limit_override":0,"spread_tasks":1},"parent_id":2,"root_id":1,"action":"filter","selected_api":"FilterAPI","title":"Only Continue if Channel ID Exists","authentication_id":null}}}]}
And just to add, it doesn’t seem to matter what filetype has been uploaded in Slack - I’m seeing PDFs, .docx, and .xlsx all get uploaded as the hydrated text files during live runs, e.g.,
Screenshots do not show how your GDrive Zap step is configured in EDIT mode.
My bad - for some reason that screenshot got dropped off in my last post:
@DennisWF
How long is the Delay For step?
File objects are temp files that expire after a short period of time.
So that may be contributing to the issue.
Instead, try using the file download URL instead of the file object.
Or try finding the Slack Message before the upload step to use to map the file object from that step.
Action: Slack - Get Message
The Delay step was something I just added. It’s for 2 mins, and no live trigger events have occurred since I added it - the problem runs have all happened before I added the Delay.
ChatGPT suggested the below, so I added the Delay to see if it might resolve the issue. Haven’t had a live run since though - it’s in my client’s Slack workspace, so I need to get him to upload a file.
——
Hydration isn’t cached – every downstream step (or replay) fetches the file again from Slack.
Files are sometimes “not ready” the moment the Slack event fires (virus scan / indexing lag).
Transient Slack/API errors (rate limits, 5xx) surface as None, but disappear on retry.
Replays run later, so they often succeed even though nothing in the Zap changed.
@DennisWF
If it is still not working, then try this suggestion…
Try finding the Slack Message before the upload step to use to map the file object from that step.
@Troy Tessalone - i’ll try that now. In terms of the suggestion to use the private download URL instead of the file object, how would that work? My assumption was that the private URL would only be accessible with Slack authentication, and that actions in other apps would therefore not be able to use that. Is my understanding off?
Thanks again!
@Troy Tessalone Just tried this in testing -
When I use the URL Private Downloadinstead of the File (exists but not shown) object, the uploaded file looks like this on test runs (I think because the GDrive action doesn’t inherit the permissions to the file URL from Slack):
I also tried adding a Get Message by Timestamp step, but that only returns URLs for the file, and not a File object, so since Google Drive can’t access the URLs, I’m getting the same result upon upload.
I think I’ve figured it out.
I created a Custom Action to make the file public, or just return the existing public permalink if it’s already public.
// Exporting an async function to check and enable public sharing for a specific file in Slack using the file ID. export async function enablePublicSharing({ fileId }: { fileId: string }): Promise<object> { // Step 1: Check if the file is already public by calling the files.info endpoint. const infoUrl = `https://slack.com/api/files.info?file=${fileId}`;
// Use fetchWithZapier to make the API request with the GET method. const infoResponse = await fetchWithZapier(infoUrl, { method: 'GET' });
// Throw an error if the response is not ok. await infoResponse.throwErrorIfNotOk();
// Parse the JSON response. const infoData = await infoResponse.json();
// Check if the file is already public. if (infoData.ok && infoData.file && infoData.file.public_url_shared) { // If the file is already public, return the existing public permalink. return { result: infoData.file.permalink_public }; }
// Step 2: If the file is not public, enable public sharing by calling the files.sharedPublicURL endpoint. const shareUrl = `https://slack.com/api/files.sharedPublicURL`;
// Prepare the request body with the file ID. const requestBody = { file: fileId };
// Use fetchWithZapier to make the API request with the POST method and the request body. const shareResponse = await fetchWithZapier(shareUrl, { method: 'POST', headers: { 'Content-Type': 'application/json; charset=utf-8' // Specify charset to avoid missing charset warning }, body: JSON.stringify(requestBody) });
// Throw an error if the response is not ok. await shareResponse.throwErrorIfNotOk();
// Parse the JSON response. const shareData = await shareResponse.json();
// Check if the response indicates success and contains the file object with a public URL. if (shareData.ok && shareData.file && shareData.file.permalink_public) { return { result: shareData.file.permalink_public }; }
// If the response does not contain the expected data, return an error message. return { result: 'Failed to retrieve or enable public permalink' }; }
Then, to generate a public download permalink, I used a Formatter → Split Text step to extract the pub_secret from the public permalink:
The public download URL format is just private_download_url?pub_secret=pub_secret so I fed that into the GDrive upload step:
Finally, at the end I want to revoke the public URL for the file for security, so I created another Custom Action for that (for some reason, I get a permissions issue if I just try to do this with a direct API action, but via a Custom Action it’s fine:
export async function revokeSlackFilePublicURL(params: { fileId: string }): Promise<{ result: boolean }> { // Extract the fileId from the input object const { fileId } = params;
// Define the API endpoint for revoking public URL access const url = 'https://slack.com/api/files.revokePublicURL';
// Prepare the request body with the file ID const requestBody = { file: fileId };
// Make the API call using fetchWithZapier const response = await fetchWithZapier(url, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(requestBody) });
// Throw an error if the response is not ok await response.throwErrorIfNotOk();
// Parse the JSON response const data = await response.json();
// Return the result indicating success return { result: data.ok }; }
Here’s a full outline of the new version of the Zap - I think this finally does the trick!
@Troy Tessalone yeah, those are the endpoints the Custom Actions are using. But if I try to use them via an API step with the Slack app, I get an error saying that I don’t have the required scopes. When I use them via Custom Actions, using the same auth, they work. Have you ever run into something like this?
Add a short delay before uploading to Google Drive. It helps Zapier get the full Slack file and upload it properly.