---
title: "Troubleshooting Ingress"
date: "2026-11-10"
authors: "Darryn Campbell"
tags: "guide"
---

# Troubleshooting Ingress

LiveKit Ingress brings media from outside LiveKit into a room. It accepts three types of source:

- **RTMP and RTMPS**, pushed from an encoder such as OBS, ffmpeg, or a hardware camera.
- **WHIP**, a WebRTC-based protocol, also pushed from an encoder.
- **URL input**, where Ingress pulls a file or stream from a URL you provide: either an HTTP(S) URL, such as an HLS stream or an MP4 file, or an `srt://` URL for a stream served by an SRT server.

The Ingress service receives the media and publishes it into the room as a participant, so other participants subscribe to its tracks just as they would to anyone else's. Ingress transcodes RTMP and URL input: it decodes the stream and re-encodes it for WebRTC. WHIP media passes through as-is by default, but you can enable transcoding.

<Mermaid
  chart={`flowchart LR
ENC["Encoder<br>OBS, ffmpeg, camera"]
SRC["Media URL<br>HTTP(S) or SRT"]
ING["LiveKit Ingress<br>transcode or passthrough"]
ROOM["LiveKit room"]
ENC -->|"RTMP / RTMPS"| ING
ENC -->|"WHIP"| ING
SRC -.->|"URL input, pulled by Ingress"| ING
ING -->|"Publishes tracks"| ROOM
`}
/>

To learn how to create and configure an Ingress, see the [Ingress overview](https://docs.livekit.io/transport/media/ingress-egress/ingress/).

## Connection issues

When the RTMP server refuses a publish request, it returns the status `NetStream.Publish.Failed`. In GStreamer, the error looks like this:

```text
ERROR: from element /GstPipeline:pipeline0/GstRtmp2Sink:rtmp2sink0: 
Failed to connect: 'publish' cmd failed: onStatus: { "level": "error", 
"code": "NetStream.Publish.Failed", "description": "Publish failed." }
```

Streaming tools such as OBS and ffmpeg hide this status behind a more generic error. ffmpeg shows something like this:

```text
[rtmp @ 0x...] Server error: Publish failed.
Error opening output rtmp://<ingress-url>/<stream-key>: Operation not permitted
```

OBS shows this error:

```text
Could not access the specified channel or stream key, please 
double-check your stream key. If it is correct, there may be a 
problem connecting to the server.
```

Each of these errors can have several causes, as listed in the following table:

| Problem                                                                                                                           | Resolution                                                                                                                                                                                                                             |
| --------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| The stream key you provided is incorrect.                                                                                         | Use the stream key returned by `CreateIngress`, and check that it matches exactly.                                                                                                                                                     |
| The stream key belongs to an Ingress that has been [deleted](https://docs.livekit.io/reference/other/ingress/api/#deleteingress). | Run `lk ingress list`. If the Ingress isn't listed, it has been deleted, and its stream key no longer works.                                                                                                                           |
| The stream key belongs to an Ingress of a different input type, for example, a WHIP stream key used with an RTMP encoder.         | Run `lk ingress list --id <ingress-id> --json`. If `state.error` is `invalid ingress type`, change your encoder's settings to match the Ingress, or create an Ingress of the right type.                                               |
| The Ingress isn't [enabled](https://docs.livekit.io/reference/other/ingress/api/#ingressinfo).                                    | Run `lk ingress list --id <ingress-id> --json` and check whether `enabled` is `false`. If it is, re-enable it with [`UpdateIngress`](https://docs.livekit.io/reference/other/ingress/api/#updateingress), setting `enabled` to `true`. |
| Some other transient issue occurred.                                                                                              | Retry after a few moments.                                                                                                                                                                                                             |

### The connection times out

If your encoder hangs and eventually times out instead of failing immediately, the connection probably never reached LiveKit. To confirm, check your [webhooks](https://docs.livekit.io/intro/basics/rooms-participants-tracks/webhooks-events/#webhook-events) for `ingress_started` and `ingress_ended` events. If neither arrives and the [Ingress state](https://docs.livekit.io/reference/other/ingress/api/#ingressstate) doesn't change, the connection never got through.

The usual cause is a firewall. Plain RTMP uses TCP port 1935, which corporate and venue networks often block. RTMPS uses port 443, which is almost always open, so the quickest fix is to switch your encoder to the `rtmps://` URL.

### Media connection failure

This section applies only to WHIP. WHIP sets up the session with an HTTP request, but the media travels over a separate WebRTC connection, usually over UDP. That connection can fail even when the HTTP request succeeds.

What you see depends on whether the Ingress transcodes:

- **Without transcoding (the default for WHIP),** the Ingress looks healthy at first. It joins the room and reports `ENDPOINT_PUBLISHING`, but about 15 seconds later the participant leaves and the Ingress returns to `ENDPOINT_INACTIVE`.
- **With transcoding,** the Ingress stays in `ENDPOINT_BUFFERING` and, about 10 seconds later, moves to `ENDPOINT_ERROR` with the error `source encoder not ready`.

In both cases, the most likely cause is that the media connection couldn't be established. The stream itself is fine; the WebRTC connection between your encoder and LiveKit just never completed.

One possible cause is a firewall blocking UDP, which WebRTC prefers. When UDP is blocked, some encoders, such as GStreamer's `whipsink`, fall back to ICE over TCP, which uses port 7881 on LiveKit Cloud. Others, including OBS, don't fall back, so the connection fails. If you can't open UDP, make sure TCP port 7881 is reachable and use an encoder that supports ICE over TCP.

On self-hosted deployments, media connections can also fail if something on the network path between the WHIP source and the Ingress service doesn't support IPv6. One of the simplest fixes is to disable IPv6 on the server.

Your encoder can take longer than Ingress to notice a media connection failure. OBS keeps trying for about a minute, then shows this error:

```text
An unexpected error occurred when trying to connect to the
server. More information in the log file.
```

OBS's log file shows a connection that never completes: `PeerConnection state is now: Connecting`, followed by `Failed`, with no `Connected` in between.

If a WHIP stream works for several minutes or hours and then freezes, the likely cause is a change along your network path that affects UDP traffic.

## Codec issues

If a track uses a codec that Ingress doesn't support, that track can be missing from the room with no error reported. For example, at the time of writing, Ingress doesn't support H.265 video over RTMP. If you send it, the Ingress participant publishes only the audio track. Make sure your encoder sends a supported codec, such as H.264. The [encoder documentation](https://docs.livekit.io/transport/media/ingress-egress/ingress/encoders/) has example configurations for each input type.

## Regional considerations

If viewers see high latency or frozen frames, check which region the Ingress connected to, as shown in the session view of the LiveKit Cloud dashboard. Ingress is routed to a LiveKit region based on network conditions, but if the Ingress consistently connects to a region far from your streamers or audience, it's worth investigating further.

## Best practices

**An Ingress creates its room if it doesn't already exist.** If you need to control the room's attributes, call [`CreateRoom`](https://docs.livekit.io/reference/other/roomservice-api/#createroom) before you start the stream.

**Delete the Ingress before the room.** If you call `DeleteRoom` while an encoder is still sending to an Ingress in that room, the Ingress rejoins, and the room is recreated.

**Reuse Ingresses.** An RTMP or WHIP Ingress isn't a single stream; it's a long-lived endpoint that you can stream to many times. Every RTMP and WHIP Ingress counts toward your project's [concurrent imports](https://livekit.com/pricing#concurrent-imports) limit for as long as it exists, even when nothing is streaming to it, so reuse your Ingresses and delete any you no longer need. Otherwise, `CreateIngress` eventually fails with `total ingress object limit exceeded`.

**URL input starts immediately.** Unlike RTMP and WHIP, which wait for an encoder, a URL Ingress starts pulling its source as soon as you create it. Only create it when you're ready for it to publish, and [check its state](https://docs.livekit.io/reference/other/ingress/api/#listingress) right after you create it.

**You're billed for transcoding minutes whether or not anyone is watching.** Add application logic so you don't waste minutes, for example, by listening for `ingress_started` events and [deleting](https://docs.livekit.io/reference/other/ingress/api/#deleteingress) any Ingress that runs longer than a set duration.

***

If you're still having issues with Ingress, join the LiveKit [developer community](https://community.livekit.io) and share what you're seeing.