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
- 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.
- Re-enable Socket Mode in the Slack app settings (Socket Mode toggles off when scopes are changed and the app is not reinstalled).
- If data.error is 'invalid_auth', regenerate the app-level token and update channel config.
- 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
- Keep Socket Mode enabled in the Slack app settings — toggling scopes off re-disables it.
- After changing app scopes, always reinstall the app to the workspace so tokens refresh.
- Store the xapp- token in a config field validated against the xapp-1- prefix on write.
- Log the Slack error string verbatim when this throws — it maps to documented Slack error codes.
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
- Failed to open Socket Mode connection: HTTP ${response.statu
- Slack API error ${method}: ${data.error ?? 'unknown error'}
- Slack bot token (xoxb-...) is required
- Slack API error ${method}: HTTP ${response.status} - ${error
- Private key must be a non-empty string
AI-assisted analysis of CherryHQ/cherry-studio@726446b54c (2026-08-12).
Data as JSON: /api/errors/81b34ff518089564.
Report an issue: GitHub.