hookdeck listen with a comma-separated source list or * panics when none of the named sources has a CLI connection yet. Once a connection does exist, the same command stops panicking but forwards only one source's events, with no warning that the others were dropped.
Reproduced on a Console (guest) project. I have not tested an authenticated Event Gateway project, so I don't know whether that path behaves the same.
Environment
hookdeck-cli 2.5.0, installed via npm
- Linux
- Console project (created through the Console Sources API, no account)
Steps to reproduce
1. Create two sources that share a session, so both belong to the same project and share a CLI key:
curl -sS -c cookies.txt -X POST https://console.hookdeck.com/
curl -sS -b cookies.txt -c cookies.txt -X POST https://console.hookdeck.com/
Both responses carry the same cli_key. The names differ: the first is Source, the second gets a random suffix such as Source-b4r7.
2. Start from a clean config, since the panic depends on no CLI connection existing yet:
rm -rf ~/.config/hookdeck
3. Listen to both sources:
hookdeck listen 3000 'Source,Source-b4r7' --cli-key <cli_key>
Actual
Saved CLI key for Sandbox. Future runs won't need --cli-key.
panic: runtime error: index out of range [0] with length 0
goroutine 1 [running]:
github.com/hookdeck/hookdeck-cli/pkg/listen.Listen(...)
/pkg/listen/listen.go:100 +0x1495
github.com/hookdeck/hookdeck-cli/pkg/cmd.(*listenCmd).runListenCmd(...)
/pkg/cmd/listen.go:501 +0x4f6
Exit code 2. hookdeck listen 3000 '*' --cli-key <cli_key> panics identically.
Note that --cli-key itself works: the key is accepted and ~/.config/hookdeck/config.toml is written with project_mode = 'console' before the panic.
Expected
Either both sources are forwarded, or a clear error explaining what is unsupported. Not a stack trace.
Second behavior, after a connection exists
Run a single-source listen first, which auto-creates the CLI connection:
hookdeck listen 3000 'Source'
# There's no CLI destination connected to Source, creating one named cli-Source
Then re-run the multi-source command. It no longer panics, but only Source is listed as listening. Source-b4r7 is absent, and nothing says so. * behaves the same way.
This is worse than the crash, because it looks like it worked. Sending a request to each source's ingest URL during a multi-source session:
| Ingest URL |
Ingest response |
Reached localhost:3000 |
| source A |
200 |
yes |
| source B |
200 |
no |
Source B's request is accepted and never forwarded. From the terminal there is no indication anything was dropped.
Root cause
ensureConnections in pkg/listen/connection.go returns early whenever isMultiSource is set, without creating anything:
if len(connections) > 0 || isMultiSource {
return connections, nil
}
So in multi-source mode the returned slice is exactly whatever CLI connections already existed, which is empty on a fresh project.
Listen in pkg/listen/listen.go:100 then indexes it unconditionally:
currentCLIPath := connections[0].Destination.GetCLIPath()
Hence index out of range [0] with length 0. The guarded checks around it (len(connections) > 1 just above, len(connections) == 1 just below) never get a chance to run, because the unguarded index sits between them.
The same early return explains the second behavior. After a single-source run, exactly one CLI connection exists, so the slice has one element, connections[0] succeeds, and only that source is listened to. The source without a connection is silently skipped rather than being created or reported.
Related
--path is rejected outright with multiple sources:
Can only set a CLI path when listening to a single source
Worth noting because the cmd_hint returned by the Console Sources API includes --path /webhooks, so copying that hint and substituting a source list produces this error rather than the panic.
Open question
The early return on isMultiSource looks deliberate, so the design question is whether multi-source listen should auto-create CLI connections for sources that lack them, or whether that is intentionally out of scope.
If it is out of scope, the fix is presumably a guard plus an actionable error naming the sources without connections. If it is in scope, multi-source needs to create the missing connections the way the single-source path does. Either way, the silent-drop behavior seems worth addressing separately from the panic, since it persists once connections exist.
I have not attempted a fix.
hookdeck listenwith a comma-separated source list or*panics when none of the named sources has a CLI connection yet. Once a connection does exist, the same command stops panicking but forwards only one source's events, with no warning that the others were dropped.Reproduced on a Console (guest) project. I have not tested an authenticated Event Gateway project, so I don't know whether that path behaves the same.
Environment
hookdeck-cli2.5.0, installed via npmSteps to reproduce
1. Create two sources that share a session, so both belong to the same project and share a CLI key:
Both responses carry the same
cli_key. The names differ: the first isSource, the second gets a random suffix such asSource-b4r7.2. Start from a clean config, since the panic depends on no CLI connection existing yet:
rm -rf ~/.config/hookdeck3. Listen to both sources:
Actual
Exit code 2.
hookdeck listen 3000 '*' --cli-key <cli_key>panics identically.Note that
--cli-keyitself works: the key is accepted and~/.config/hookdeck/config.tomlis written withproject_mode = 'console'before the panic.Expected
Either both sources are forwarded, or a clear error explaining what is unsupported. Not a stack trace.
Second behavior, after a connection exists
Run a single-source listen first, which auto-creates the CLI connection:
Then re-run the multi-source command. It no longer panics, but only
Sourceis listed as listening.Source-b4r7is absent, and nothing says so.*behaves the same way.This is worse than the crash, because it looks like it worked. Sending a request to each source's ingest URL during a multi-source session:
localhost:3000200200Source B's request is accepted and never forwarded. From the terminal there is no indication anything was dropped.
Root cause
ensureConnectionsinpkg/listen/connection.goreturns early wheneverisMultiSourceis set, without creating anything:So in multi-source mode the returned slice is exactly whatever CLI connections already existed, which is empty on a fresh project.
Listeninpkg/listen/listen.go:100then indexes it unconditionally:Hence
index out of range [0] with length 0. The guarded checks around it (len(connections) > 1just above,len(connections) == 1just below) never get a chance to run, because the unguarded index sits between them.The same early return explains the second behavior. After a single-source run, exactly one CLI connection exists, so the slice has one element,
connections[0]succeeds, and only that source is listened to. The source without a connection is silently skipped rather than being created or reported.Related
--pathis rejected outright with multiple sources:Worth noting because the
cmd_hintreturned by the Console Sources API includes--path /webhooks, so copying that hint and substituting a source list produces this error rather than the panic.Open question
The early return on
isMultiSourcelooks deliberate, so the design question is whether multi-source listen should auto-create CLI connections for sources that lack them, or whether that is intentionally out of scope.If it is out of scope, the fix is presumably a guard plus an actionable error naming the sources without connections. If it is in scope, multi-source needs to create the missing connections the way the single-source path does. Either way, the silent-drop behavior seems worth addressing separately from the panic, since it persists once connections exist.
I have not attempted a fix.