chenhg5/cc-connect · error
received HTML response (likely missing auth); first 100 byte
Error message
received HTML response (likely missing auth); first 100 bytes: %s
What it means
After reading the body, downloadSlackFile sanity-checks whether Slack returned an HTML page (starting with <!DOCTYPE or <html) instead of the expected binary file content. This almost always means the request was not authenticated and Slack served a login/error page. The first 100 bytes are included to aid diagnosis.
Source
Thrown at platform/slack/slack.go:587
if err != nil {
return nil, fmt.Errorf("%s", core.RedactToken(err.Error(), p.botToken))
}
defer resp.Body.Close()
// Check if we got an unexpected status code (e.g., redirect to login page)
if resp.StatusCode != http.StatusOK {
body, _ := io.ReadAll(io.LimitReader(resp.Body, 1024))
return nil, fmt.Errorf("download failed with status %d: %s", resp.StatusCode, string(body))
}
data, err := io.ReadAll(resp.Body)
if err != nil {
return nil, fmt.Errorf("read response body: %w", err)
}
// Basic sanity check: detect if we received HTML instead of binary data
if len(data) > 0 && (bytes.HasPrefix(data, []byte("<!DOCTYPE")) || bytes.HasPrefix(data, []byte("<html"))) {
return nil, fmt.Errorf("received HTML response (likely missing auth); first 100 bytes: %s", string(data[:min(100, len(data))]))
}
return data, nil
}
func (p *Platform) ReconstructReplyCtx(sessionKey string) (any, error) {
// slack:{channel}:{user} | slack:{channel}:t:{threadTS} | slack:{channel}
parts := strings.SplitN(sessionKey, ":", 3)
if len(parts) < 2 || parts[0] != "slack" {
return nil, fmt.Errorf("slack: invalid session key %q", sessionKey)
}
rc := replyContext{channel: parts[1]}
// Thread-scoped keys carry the thread root ts as a "t:<ts>" suffix; preserve
// it so proactive replies (cron, send-to-session, restart/model/delete
// notifications) post into the original thread instead of the channel root.
if len(parts) == 3 && strings.HasPrefix(parts[2], "t:") {
rc.timestamp = strings.TrimPrefix(parts[2], "t:")
}View on GitHub (pinned to 4000b2338a)
Solutions
- Ensure the request carries the bot token: pass slack.MsgOption or set Authorization: Bearer <token> on the http request using the file's url_private_download field
- Verify the bot token has the files:read scope (check via auth.test / app config)
- Use file.URLPrivateDownload, not file.Permalink or URLPrivate, for programmatic download
- Inspect the logged first-100-bytes snippet to confirm it is a login/permission page
Example fix
// before
req, _ := http.NewRequest("GET", fileURL, nil)
resp, err := http.DefaultClient.Do(req)
// after
req, _ := http.NewRequest("GET", fileURL, nil) // fileURL = file.URLPrivateDownload
req.Header.Set("Authorization", "Bearer "+p.botToken)
resp, err := http.DefaultClient.Do(req) Defensive patterns
Strategy: validation
Validate before calling
func fileURLIsDownloadable(f *slack.File) bool {
return f.URLPrivateDownload != "" // use this URL + Bearer token
} Try / catch
data, err := downloadSlackFile(f.URLPrivateDownload, token)
if err != nil {
if strings.Contains(err.Error(), "received HTML response") {
return fmt.Errorf("slack auth/URL problem: %w", err) // fix token/URL, don't retry
}
return err
} Prevention
- Always download from url_private_download with an Authorization: Bearer bot token
- Verify files:read scope when installing the Slack app
- Never use public_permalink for programmatic downloads
- Never hit the URL without the auth header
When it happens
Trigger: The file URL requires auth but the request was sent without (or with an invalid/expired) Authorization: Bearer token; a redirect landed on a Slack sign-in HTML page; the URL is a browser page URL rather than the url_private_download endpoint.
Common situations: Using public_permalink instead of url_private_download; token lacking files:read scope; user token vs bot token mismatch; expired token after workspace app re-install; corporate proxy returning an HTML interstitial.
Understand the failure class
Background: "invalid response format", "malformed payload", "missing data field": when an API returns 200 but the response shape is wrong — this error's family across 23 libraries.
Related errors
- read response body: %w
- webex: unauthorized (401) — check bot token
- acp: authenticate (%s): %w
- remote returned non-zero code
- code=%d msg=%s
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/6659fab2c914490f.
Report an issue: GitHub.