{
  "id": "P146",
  "slug": "slack-files-getuploadurlexternal-completeuploadexternal-bytes-upload-no-file-appears-channel",
  "status": "verified-page-ready",
  "product": "Slack file upload",
  "family": "Endpoint workflow replacement",
  "canonical_url": "https://gitdocs.org/fix/slack-files-getuploadurlexternal-completeuploadexternal-bytes-upload-no-file-appears-channel",
  "query_alias_url": "https://gitdocs.org/q/slack-files-getuploadurlexternal-completeuploadexternal-bytes-upload-no-file-appears-channel",
  "markdown_url": "https://gitdocs.org/fix/slack-files-getuploadurlexternal-completeuploadexternal-bytes-upload-no-file-appears-channel.md",
  "json_url": "https://gitdocs.org/api/fixes/slack-files-getuploadurlexternal-completeuploadexternal-bytes-upload-no-file-appears-channel.json",
  "canonical_query": "Slack files.getUploadURLExternal completeUploadExternal bytes upload no file appears channel",
  "observed_codex_queries": [
    "Slack files.getUploadURLExternal completeUploadExternal bytes upload no file appears channel",
    "files.getUploadURLExternal files.completeUploadExternal site:api.slack.com",
    "https://api.slack.com/methods/files.getUploadURLExternal",
    "https://api.slack.com/methods/files.completeUploadExternal"
  ],
  "organic_dependency_search_count": 4,
  "affected_versions": "Slack apps migrating from `files.upload` to the external upload sequence.",
  "exact_errors": [
    "Upload URL request succeeds but no file appears in the channel",
    "files.completeUploadExternal was not called or used the wrong file_id"
  ],
  "diagnosis": "The upload URL step only reserves a file. The bytes must be uploaded to the returned URL, then `files.completeUploadExternal` must complete the same file ID and share it to a channel.",
  "before": "await client.files.getUploadURLExternal({ filename: \"report.txt\", length: bytes.length });",
  "after": "const upload = await client.files.getUploadURLExternal({ filename: \"report.txt\", length: bytes.length });\nawait fetch(upload.upload_url, { method: \"POST\", body: bytes });\nawait client.files.completeUploadExternal({\n  files: [{ id: upload.file_id, title: \"report.txt\" }],\n  channel_id: channelId,\n});",
  "verification": "node scripts/slack-upload-smoke.js",
  "unsafe_fixes": [
    "Do not retry `completeUploadExternal` blindly; the completion call is not a general idempotent repair path."
  ],
  "last_verified_at": "2026-06-25",
  "neutral_validation": {
    "organic_search_observed": true,
    "organic_strict_pass": true,
    "no_web_counterfactual_run": false,
    "no_web_strict_pass": null,
    "search_necessity_under_fixture": null,
    "no_web_oracle_note": "Observed query evidence is separated from necessity proof; no-web and stale-contract counterfactuals should be tracked separately."
  },
  "source_trail": [
    {
      "url": "https://docs.slack.dev/changelog/2024-04-a-better-way-to-upload-files-is-here-to-stay/",
      "label": "Slack files.upload retirement"
    },
    {
      "url": "https://api.slack.com/methods/files.getUploadURLExternal",
      "label": "Official reference opened by Codex"
    },
    {
      "url": "https://api.slack.com/methods/files.completeUploadExternal",
      "label": "Official reference opened by Codex"
    },
    {
      "url": "https://docs.slack.dev/changelog/2024-04-a-better-way-to-upload-files-is-here-to-stay",
      "label": "Authoritative source"
    }
  ],
  "source_github_links": []
}
