What Slack is actually checking during verification
Slack's Event Subscriptions setup step is a synchronous handshake: Slack POSTs a JSON payload containing a `challenge` field to the URL you entered, and your endpoint must reply with that same string in the response body before Slack will save the URL. This is separate from actually receiving events later — it only tests that something is listening and echoing correctly right now.
Community reports of this exact message describe it happening the moment a user pastes an n8n webhook URL into Slack's Event Subscriptions field and clicks outside the box, which is when Slack fires the verification request. If the workflow behind that webhook is not currently listening, Slack gets no response at all and shows this message.
The error is about the verification handshake, not your event subscriptions or scopes. Do not touch OAuth scopes to fix this — check whether anything is listening on that exact URL.
Confirm which of the five common causes applies
| Cause | How to tell | Fix |
|---|
| Workflow not active | Toggle in editor header shows off, or was saved without activating | Turn the Active toggle on and re-save |
| Test URL pasted instead of Production | URL contains "webhook-test" instead of "webhook" | Copy the Production URL from the node, not the Test URL |
| Reverse proxy strips or buffers POST body | curl direct to n8n works, curl through the domain does not | Fix proxy to pass full POST body and headers through |
| Node returns wrapped JSON instead of raw challenge | curl gets a response, but it's `{"challenge":"..."}` not the bare string | Add explicit Respond to Webhook node returning raw text |
| Self-hosted instance has no public URL at all | No domain, or localhost only | Use ngrok/Cloudflare Tunnel, or Socket Mode as an alternative |
Fix in order, testing after each step
First, activate the workflow (toggle on, saved) and use the Production URL from the webhook node — Slack's setup step needs a URL that is listening independent of the editor being open. Confirm the toggle is actually on, not just that the workflow was saved.
Second, if you are behind a reverse proxy, temporarily bypass it (hit n8n directly on its port) to isolate whether the proxy is the problem. If direct access verifies successfully but the proxied domain does not, the proxy configuration — not n8n or Slack — is the fix target.
Third, if the webhook path responds to a manual curl POST with a JSON body but Slack still rejects it, inspect what the workflow actually returns. n8n's default webhook response echoes the request body as JSON; Slack does not want the whole body echoed back as JSON, it wants the literal challenge value in the response. Some node configurations need an explicit Respond to Webhook node set to plain text with the challenge value passed through, rather than relying on the default response mode.
curl -X POST https://your-n8n-domain/webhook/your-path \
-H "Content-Type: application/json" \
-d '{"type":"url_verification","challenge":"test123"}'
# Expected: raw response body is exactly: test123
# NOT: {"challenge":"test123"}
# NOT: empty body
# NOT: connection refused / timeout
If you are running self-hosted n8n with no public URL
This is a distinct, common variant on self-hosted setups: n8n running on a local machine or an internal network has nothing Slack's servers on the public internet can reach at all, regardless of activation state or response format. Slack's verification request needs to reach a real, internet-routable HTTPS endpoint.
Two established options exist. A tunneling tool such as ngrok or Cloudflare Tunnel exposes your local n8n instance at a temporary public HTTPS URL you then paste into Slack — this is the most direct fix and requires no change to how the Slack Trigger node itself works. The alternative is Socket Mode, a different Slack connection model that uses an outbound WebSocket connection instead of an inbound HTTP endpoint, which avoids needing a public URL at all but requires a different (community, not built-in) n8n node and is generally treated as a development-time option rather than the production-recommended architecture.
For a workflow that will eventually run in production, prefer getting a stable public URL working (via your normal reverse proxy or a paid tunnel plan) over building around Socket Mode long-term, since Slack's own guidance treats the Events API over HTTPS as the standard production approach.
Verify before re-saving in Slack
- curl the webhook URL directly with a fake challenge payload and confirm the response body is the bare challenge string, not JSON, not empty.
- If curl succeeds but Slack still fails, check for a proxy or CDN in front of the domain that may treat the two paths (curl vs Slack's request) differently — Slack's request includes specific headers some WAFs treat differently.
- If self-hosted with no public URL, confirm the tunnel (ngrok/Cloudflare) is actually running and the forwarded URL, not a cached old one, is what's pasted into Slack — tunnel URLs typically change on every restart unless you are on a paid plan with a reserved domain.
- Only re-click "Save" in Slack's Event Subscriptions page after the curl test passes — repeatedly re-saving without fixing the underlying response does not change the outcome.
Sources checked for this guide
The verification handshake behavior is Slack's documented Events API mechanism; the specific n8n reproduction and community-reported causes come from the threads below.
Frequently asked questions
Do I need to change Slack app scopes to fix the challenge parameter error?
No. This is a verification-handshake failure, not a permissions problem. Scopes control what your app can do after events are subscribed; the challenge check only confirms something is listening and echoing correctly right now.
Which URL should I paste into Slack — Test or Production?
Use the Production URL with the workflow activated (toggle on). The Test URL only listens while the editor has an active "Listen for test event" session, which is not reliable for Slack's one-time verification request.
My curl test works but Slack still fails — what else could it be?
Check for a reverse proxy, CDN, or WAF in front of your n8n domain that may treat Slack's specific request headers differently than a plain curl request. Bypass the proxy temporarily to confirm n8n itself is not the problem.
My n8n is only running on my laptop with no domain at all — what do I do?
Use a tunneling tool like ngrok or Cloudflare Tunnel to get a temporary public HTTPS URL, and paste that into Slack instead of localhost. This is the standard approach for local development against services (like Slack) that require a publicly reachable endpoint.