Skip to content

listen panics on multiple sources when no CLI connection exists yet, and silently listens to one source once it does #371

Description

@leggetter

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions