[BUG] http hooks with json don't work.

Resolved 💬 8 comments Opened Mar 4, 2026 by tonyadamsmba Closed Apr 4, 2026

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

The ECONNREFUSED at the Claude Code client level with zero requests reaching Cloudflare confirms this isn't your config or your endpoint. It's an internal TCP connection issue in Claude Code's HTTP hook implementation.

Let me check if there's been any fix in newer releases since v2.1.66.Here's what I found. This appears to be a Bun HTTP client issue — the same pattern shows up in multiple GitHub issues where system-level curl succeeds but Claude Code's internal makeRequest calls fail with ECONNREFUSED. Your diagnosis was spot on.

The core problem is that Claude Code's runtime (Bun) has known TCP connection issues that don't affect native OS networking. Issue #17541 explicitly calls this out: curl returns HTTP/2 405 (expected), TLS 1.3 handshake succeeds, API endpoint is reachable — but every makeRequest call inside Claude Code fails with Connection error. That's exactly your symptom, just manifesting through the HTTP hooks path instead of the API path.

A few things worth noting from the research:

No fix in the changelog yet. I scanned through the releases up to the latest published version and there's no mention of an HTTP hooks connectivity fix. The feature shipped in v2.1.63, and subsequent releases have addressed hook security issues (the CVE patches, statusLine/fileSuggestion trust bypass) but not this transport-level problem.

The claude-mem project hit the same wall. Their issue #717 shows the identical error pattern — "Unable to connect. Is the computer able to access the url?" — with HTTP hooks failing to reach their endpoint. Their workaround was the same as yours: fall back to command hooks.

HookLab works — but it runs on localhost. The HookLab project (a Phoenix LiveView dashboard) receives HTTP hook events successfully, but it's running as a local Docker container at localhost:4000. This suggests HTTP hooks may work for localhost targets but fail for external URLs. That's a meaningful datapoint — it could be a sandbox restriction on outbound connections from the hook executor, separate from the general Bun issue.

What I'd try next when you want to re-test:

Given that localhost appears to work, a potential workaround would be running a lightweight local proxy that receives the HTTP hook POST on localhost and forwards it to your Cloudflare Worker. Something like a tiny Node.js/Bun script or even socat. That way the hook executor only needs to reach 127.0.0.1, and your proxy handles the external hop. Not ideal, but it would get you the HTTP hook JSON payloads flowing to your Worker without maintaining the full shell script chain.

Alternatively, you could file this specifically as an HTTP hooks bug on the repo — the existing ECONNREFUSED issues are all about API connectivity, not hooks. A targeted report with your Cloudflare observability evidence (zero requests received) would be compelling since it clearly isolates the problem to Claude Code's outbound HTTP hook client.

What Should Happen?

Yeah, that's frustrating — you did everything right on the Worker side. The ECONNREFUSED at the Claude Code client level with zero requests reaching Cloudflare confirms this isn't your config or your endpoint. It's an internal TCP connection issue in Claude Code's HTTP hook implementation.

Let me check if there's been any fix in newer releases since v2.1.66.Here's what I found. This appears to be a Bun HTTP client issue — the same pattern shows up in multiple GitHub issues where system-level curl succeeds but Claude Code's internal makeRequest calls fail with ECONNREFUSED. Your diagnosis was spot on.

The core problem is that Claude Code's runtime (Bun) has known TCP connection issues that don't affect native OS networking. Issue #17541 explicitly calls this out: curl returns HTTP/2 405 (expected), TLS 1.3 handshake succeeds, API endpoint is reachable — but every makeRequest call inside Claude Code fails with Connection error. That's exactly your symptom, just manifesting through the HTTP hooks path instead of the API path.

A few things worth noting from the research:

No fix in the changelog yet. I scanned through the releases up to the latest published version and there's no mention of an HTTP hooks connectivity fix. The feature shipped in v2.1.63, and subsequent releases have addressed hook security issues (the CVE patches, statusLine/fileSuggestion trust bypass) but not this transport-level problem.

The claude-mem project hit the same wall. Their issue #717 shows the identical error pattern — "Unable to connect. Is the computer able to access the url?" — with HTTP hooks failing to reach their endpoint. Their workaround was the same as yours: fall back to command hooks.

HookLab works — but it runs on localhost. The HookLab project (a Phoenix LiveView dashboard) receives HTTP hook events successfully, but it's running as a local Docker container at localhost:4000. This suggests HTTP hooks may work for localhost targets but fail for external URLs. That's a meaningful datapoint — it could be a sandbox restriction on outbound connections from the hook executor, separate from the general Bun issue.

What I'd try next when you want to re-test:

Given that localhost appears to work, a potential workaround would be running a lightweight local proxy that receives the HTTP hook POST on localhost and forwards it to your Cloudflare Worker. Something like a tiny Node.js/Bun script or even socat. That way the hook executor only needs to reach 127.0.0.1, and your proxy handles the external hop. Not ideal, but it would get you the HTTP hook JSON payloads flowing to your Worker without maintaining the full shell script chain.

Alternatively, you could file this specifically as an HTTP hooks bug on the repo — the existing ECONNREFUSED issues are all about API connectivity, not hooks. A targeted report with your Cloudflare observability evidence (zero requests received) would be compelling since it clearly isolates the problem to Claude Code's outbound HTTP hook client.

Error Messages/Logs

Steps to Reproduce

  1. Add an HTTP hook to ~/.claude/settings.json:

{
"hooks": {
"PreToolUse": [
{
"hooks": [
{
"type": "http",
"url": "https://claude-memory.mapmatix.com/api/hooks",
"headers": {
"Authorization": "Bearer $CLAUDE_MEMORY_API_KEY"
},
"allowedEnvVars": ["CLAUDE_MEMORY_API_KEY"]
}
],
"matcher": "*"
}
]
},
"env": {
"CLAUDE_MEMORY_API_KEY": "any-valid-token"
}
}

  1. Start a new Claude Code session (fresh startup so hooks are snapshotted)
  2. Run any tool (e.g. type a prompt that triggers a Bash or Read call)

Expected: HTTP hook POSTs to the URL and returns successfully (the endpoint returns HTTP 200 with valid JSON — verified via curl and
Node.js https.request from the same machine)

Actual: Every tool call shows PreToolUse:Bash hook error and PostToolUse:Bash hook error. The Stop event shows Stop hook error:
ECONNREFUSED.

Key diagnostic findings:

  • Zero HTTP requests reach the server (confirmed via Cloudflare Workers observability logs)
  • curl -X POST https://claude-memory.mapmatix.com/api/hooks returns 200 from the same machine
  • node -e "require('https').get('https://...', res => console.log(res.statusCode))" returns 200
  • DNS resolves correctly (both IPv4 and IPv6)
  • No proxy settings configured (HTTP_PROXY, HTTPS_PROXY unset)
  • No httpHookAllowedUrls or allowedHttpHookUrls restrictions set
  • settings.json is valid JSON
  • Errors are non-blocking (tools still execute) but displayed on every call
  • Claude Code version: 2.1.66, macOS Darwin 25.3.0

Claude Model

None

Is this a regression?

Yes, this worked in a previous version

Last Working Version

_No response_

Claude Code Version

2.1.66

Platform

Anthropic API

Operating System

macOS

Terminal/Shell

Terminal.app (macOS)

Additional Information

_No response_

View original on GitHub ↗

This issue has 8 comments on GitHub. Read the full discussion on GitHub ↗