The API never changes the destination of an existing connection ("A connection's source and destination cannot be updated", core server/api/routes/gateway/webhook.ts#L312). The CLI sends the change anyway and reports success, so the user thinks the connection was re-pointed when it wasn't.
Repro
Existing connection deepgram-tts with destination local-deepgram (production, CLI built from main, 2026-10-02):
| Command |
Result |
gateway connection upsert deepgram-tts --source-name deepgram-tts --source-type WEBHOOK --destination-name local-deepgram-tts --destination-type CLI --destination-cli-path /tts/webhook |
exit 0, destination unchanged. local-deepgram-tts is created as an orphan |
gateway connection upsert deepgram-tts --destination-id des_NEW |
422 value must contain at least one of [source_id, source] |
gateway connection upsert deepgram-tts --source-id src_X --destination-id des_NEW |
exit 0, destination unchanged |
gateway connection update web_ID --destination-id des_NEW |
exit 0, prints the old destination path, destination unchanged |
Cause
Suggested fix
upsert: when the connection exists and the requested destination (ID or name) differs from its current one, exit non-zero before calling the API. Say a connection's destination can't be changed, and suggest creating a new connection or deleting and recreating it.
- Do this before the inline destination upsert, so no orphan is created.
update: remove --destination-id and --source-id, or error when they differ from the current values.
- Count
--destination-id and --destination-name in needsExistingConnection().
- Apply the same checks to the MCP
gateway_connections_write tool.
The API never changes the destination of an existing connection ("A connection's source and destination cannot be updated", core
server/api/routes/gateway/webhook.ts#L312). The CLI sends the change anyway and reports success, so the user thinks the connection was re-pointed when it wasn't.Repro
Existing connection
deepgram-ttswith destinationlocal-deepgram(production, CLI built frommain, 2026-10-02):gateway connection upsert deepgram-tts --source-name deepgram-tts --source-type WEBHOOK --destination-name local-deepgram-tts --destination-type CLI --destination-cli-path /tts/webhooklocal-deepgram-ttsis created as an orphangateway connection upsert deepgram-tts --destination-id des_NEWvalue must contain at least one of [source_id, source]gateway connection upsert deepgram-tts --source-id src_X --destination-id des_NEWgateway connection update web_ID --destination-id des_NEWCause
destination_idbefore updating (server/controllers/Webhook.ts#L159-L162). The inline destination is still upserted by name first, which leaves the orphan.PUT /connections/:idonly acceptsname,descriptionandrules, and validation runs withstripUnknown: true(server/api/middlewares/validate.ts#L20), sodestination_idis silently dropped. The CLI sends it frompkg/cmd/connection_update.go#L110-L112and advertises--destination-idas "Update destination by ID".needsExistingConnection()doesn't count--destination-id, so the CLI never looks up the existing source (pkg/cmd/connection_upsert.go#L304-L345).Suggested fix
upsert: when the connection exists and the requested destination (ID or name) differs from its current one, exit non-zero before calling the API. Say a connection's destination can't be changed, and suggest creating a new connection or deleting and recreating it.update: remove--destination-idand--source-id, or error when they differ from the current values.--destination-idand--destination-nameinneedsExistingConnection().gateway_connections_writetool.