CherryHQ/cherry-studio · error · Error

Socket Mode connection failed: ${data.error ?? 'no URL retur

Error message

Socket Mode connection failed: ${data.error ?? 'no URL returned'}

What it means

Thrown by SlackAdapter.getSocketModeUrl() when apps.connections.open returns HTTP 2xx but the parsed JSON body has ok:false or lacks the url field. This is Slack's application-level error path — the HTTP transport succeeded but Slack refused to open a Socket Mode session, and Slack includes a short error string (data.error) describing why.

Source

Thrown at src/main/ai/channels/adapters/slack/SlackAdapter.ts:275

    }
  }

  private async getSocketModeUrl(): Promise<string> {
    const response = await net.fetch(`${SLACK_API_BASE}/apps.connections.open`, {
      method: 'POST',
      headers: {
        Authorization: `Bearer ${this.appToken}`,
        'Content-Type': 'application/x-www-form-urlencoded'
      }
    })

    if (!response.ok) {
      throw new Error(`Failed to open Socket Mode connection: HTTP ${response.status}`)
    }

    const data = (await response.json()) as { ok: boolean; url?: string; error?: string }
    if (!data.ok || !data.url) {
      throw new Error(`Socket Mode connection failed: ${data.error ?? 'no URL returned'}`)
    }

    return data.url
  }

  private async startSocketMode(): Promise<void> {
    if (this.shouldStop) return

    try {
      this.cleanup()

      const wsUrl = await this.getSocketModeUrl()
      this.log.info('Connecting to Slack Socket Mode')

      const ws = new WebSocket(wsUrl)
      this.ws = ws

      ws.on('open', () => {

View on GitHub (pinned to 726446b54c)

Solutions

  1. Inspect the data.error string in the thrown message — it maps directly to a Slack documented error code; the fix follows from that specific code.
  2. Re-enable Socket Mode in the Slack app settings (Socket Mode toggles off when scopes are changed and the app is not reinstalled).
  3. If data.error is 'invalid_auth', regenerate the app-level token and update channel config.
  4. If data.error is 'missing_scope', recreate the token granting connections:write.

Example fix

// before — generic message hides which Slack error fired
if (!data.ok || !data.url) {
  throw new Error(`Socket Mode connection failed: ${data.error ?? 'no URL returned'}`)
}

// after — surface the actionable Slack error code for common cases
if (!data.ok || !data.url) {
  const hint = data.error === 'invalid_auth'
    ? ' (regenerate the xapp- token at api.slack.com/apps)'
    : data.error === 'missing_scope' ? ' (token needs connections:write)' : ''
  throw new Error(`Socket Mode connection failed: ${data.error ?? 'no URL returned'}${hint}`)
}
Defensive patterns

Strategy: try-catch

Validate before calling

// You cannot fully prevent Slack's application-level ok:false without calling the API,
// but you can pre-validate token shape to eliminate the most common cause (invalid_auth).
const APP_TOKEN_RE = /^xapp-1-[A-Za-z0-9-]+$/ // connections:write scope must also be granted

if (!APP_TOKEN_RE.test(config.app_token)) {
  throw new ConfigError('Slack app token must be xapp-1-... with connections:write scope')
}

Type guard

// Type guard for the apps.connections.open success body
interface SocketModeOpenOk {
  ok: true
  url: string
}
function isSocketModeOpenOk(data: unknown): data is SocketModeOpenOk {
  return (
    typeof data === 'object' && data !== null &&
    (data as { ok?: boolean }).ok === true &&
    typeof (data as { url?: unknown }).url === 'string'
  )
}

Try / catch

try {
  await adapter.connect(signal)
} catch (e) {
  const msg = e instanceof Error ? e.message : ''
  if (msg.startsWith('Socket Mode connection failed:')) {
    const slackError = msg.slice('Socket Mode connection failed:'.length).trim()
    if (slackError === 'invalid_auth') {
      surfaceUserError('Slack app token is invalid — regenerate at api.slack.com/apps')
    } else if (slackError === 'missing_scope') {
      surfaceUserError('Recreate the app token granting connections:write')
    } else {
      surfaceUserError(`Slack refused Socket Mode: ${slackError}`)
    }
  }
}

Prevention

When it happens

Trigger: POST to apps.connections.open returns 200 with {ok:false,error:'...'} or 200 with {ok:true} but no url. Known Slack error strings here: 'invalid_auth' (app token bad), 'not_allowed_ip_scope' (IP allowlist on the Enterprise org), 'account_inactive' (app token belongs to a deleted workspace), 'missing_scope' (token lacks connections:write). The ?? 'no URL returned' fallback covers an unexpected schema where ok is true but url is absent — rare, indicates a Slack API change.

Common situations: Socket Mode was toggled off in the Slack app settings after the token was created; the app-level token was regenerated on api.slack.com but the channel config still holds the old one; the Slack workspace was deactivated; an Enterprise Grid admin restricted which IPs can open Socket Mode connections.

Related errors


AI-assisted analysis of CherryHQ/cherry-studio@726446b54c (2026-08-12). Data as JSON: /api/errors/81b34ff518089564. Report an issue: GitHub.