Troubleshooting
Run the Doctor first (SETTINGS → HELP → RUN DOCTOR). It checks TVHeadend, the TV guide, the folders, and Plex, and links each problem it finds to the section below that fixes it.
Each section starts from what you see, then gives the cause and the fix. The sections follow the order of a first install.
NOTE
Where a fix below names an HDHomeRun or an Australian broadcaster, that is the author's own setup. Each such entry says what to do with a different tuner or in another country.
TVHeadend 401 or 403
Freetvarr shows Failed: TVHeadend rejected the credentials (HTTP 401). or the same with HTTP 403, in the wizard, in SETTINGS, or on a tab that reads from TVHeadend. Settings adds the API path that failed, such as (stage: serverinfo).
401with an empty username: TVHeadend asks for a login and Freetvarr sent none. Enter the username and password of the TVHeadend user (TVHeadend step 8).403atserverinfo: TVHeadend refused the login. Check these in order:- The password. TVHeadend keeps it under Configuration → Users → Passwords, not on the access entry. The password entry needs Enabled ticked and the same username as the access entry.
- The access entry has Enabled ticked.
- Allowed networks on the access entry includes the address Freetvarr connects from. Under host networking that is the host's LAN address. A URL of
http://127.0.0.1:9981connects from127.0.0.1instead, which a LAN prefix does not cover.
403at a later stage (status/inputs,dvr/entry/…,epggrab/channel/grid): the login works but the user lacks a right. Tick the rights in the rights table, and keep Rights ticked in the entry's Change parameters.- The order of entries: access entries are an ordered list, evaluated top to bottom, so a broader entry above yours can win.
TVHeadend's default configuration accepts HTTP Digest logins only, and Freetvarr answers Digest. To test the login outside Freetvarr, run this command in a terminal on a computer on your home network. A 200 means the login works; a 403 means it does not.
curl --digest -u <user>:<password> -o /dev/null -w '%{http_code}\n' \
http://<host-ip>:9981/api/serverinfoWizard connection test
SAVE & NEXT on the TVHEADEND step runs TEST CONNECTION and stays on the step until it passes. FINISH LATER opens a dialog: press FINISH LATER again to leave the wizard and keep what you saved, or close the dialog to go back. Freetvarr cannot record until TVHeadend is connected. To resume, open SETTINGS → HELP → REOPEN WIZARD.
- "TVHeadend URL is not configured": set the URL. Under host networking it's
http://<host-ip>:9981, nothttp://tvheadend:9981(neither Docker container is on a Docker bridge network, so container names don't resolve). TVHeadend request failed: ECONNREFUSED,ECONNABORTED(a timeout), orEHOSTUNREACH: TVHeadend isn't running, or isn't on that address and port. To read TVHeadend's log, rundocker compose logs tvheadendin a terminal in thefreetvarrfolder.TVHeadend request failed: ENOTFOUND: the hostname in the URL doesn't resolve. Use the host's IP address.AUTO-DISCOVER TVHEADENDfinds nothing: no TVHeadend answered on port9981at any address of the host. Type the URL yourself, or setTVH_URLin.env(Configuration).Connectedwith0 channels: TVHeadend has no enabled channels yet. See No channels.Connectedwith0 tuners: the Freetvarr user lacks Admin, or TVHeadend sees no tuner. See Missing tuner.
TVHeadend admin login
TVHeadend's web interface answers 403 Forbidden to the admin login: the password TVHeadend stored is not the one you are typing. Securing by hand says how to reset it with --noacl.
TEST PATH failures
TEST PATH checks a folder inside the Freetvarr Docker container, not on the host.
- "/data/recordings does not exist inside the container": the Docker compose file doesn't mount a folder at that path. Check the
volumes:of thefreetvarrservice, then rundocker compose up -d freetvarrin a terminal in thefreetvarrfolder to apply the change. - "is not readable by the container user" or "is not writable by the container user": the host folder belongs to a different user from
PUID/PGID. In a terminal on the host, runls -lnon the host folder, thenchownit to thePUID:PGIDpair both containers run as. Theinitservice gives the subfolders ofCONFIG_PATHandDATA_PATHtoPUID:PGIDon every start, so this appears only when you changePUID/PGIDor put other folders in the mount. Fix the folder the message names. - "is on the same disk as the media root but in a separate mount, so imports copy each file": this is a notice, not a failure. Imports still work. Mount one folder that holds both
recordings/andmedia/, as in One shared mount, to make them hardlinks. - "is on a different disk from the media root, so imports copy each file": this is a notice, not a failure. Imports still work. Move
recordings/andmedia/onto one disk, then mount one folder that holds both.
CHECK TVHEADEND mismatch
CHECK TVHEADEND reads the recording path from TVHeadend's default DVR profile and compares it with the "Recordings folder (as TVHeadend sees it)" field.
- "TVHeadend has no recording path. Set one in its DVR profile.": set Recording system path on the default profile (TVHeadend step 7).
- "TVHeadend records to /x, not /recordings.": change TVHeadend's path to the container path of its recordings mount (
/recordingsin the example Docker compose file), or put TVHeadend's path in the field. The field holds the path TVHeadend uses inside its own container, and that path must be the same host folder Freetvarr mounts, asrecordings_root. The two recordings paths has the detail.
Missing tuner
In TVHeadend's web interface, Configuration → DVB Inputs → TV adapters is empty, or Freetvarr's setup wizard reports 0 tuners.
- The TVHeadend container has to run with
network_mode: hostfor a tuner it finds by network broadcast, such as an HDHomeRun or a SAT>IP server (those broadcasts don't cross Docker's private bridge network). A USB or PCIe tuner needs its/dev/dvbdevices passed into the container instead. - On a Mac, Docker Desktop and OrbStack cannot find a network tuner on their own. In the wizard's
CHANNELSstep, enter the tuner's IP address and this computer's IP address, then pressUSE THIS ADDRESS. The Doctor's Tuners check links to the wizard. Or run Freetvarr with Docker on Linux (a NAS, mini PC, or Raspberry Pi). - The tuner has to be on the same part of the network as the host (those broadcasts don't cross between subnets). For a tuner on another subnet, press Enter the tuner's address in the wizard's
CHANNELSstep. A tuner plugged straight into a spare NAS port gets a link-local169.254.x.xaddress. TVHeadend still finds it, but nothing else on the LAN can reach it (Hardware). - Check the tuner answers at all. On an HDHomeRun, open
http://<hdhr-ip>/tuners.htmlin a browser. If the page does not load, the tuner has a power or network cable problem, not a TVHeadend one. See Hardware. On a USB or PCIe tuner, check/dev/dvbexists on the host and inside the container. - TVHeadend lists the tuner but Freetvarr reports
0 tuners: the Freetvarr user lacks Admin, which TVHeadend requires for the tuner status.
No channels
Freetvarr reports 0 channels, or the TV Guide has no rows.
- Each tuner in TV adapters needs Enabled ticked and your network set in its Networks field (TVHeadend step 3).
- Every mux in Configuration → DVB Inputs → Muxes ending
FAILmeans the wrong pre-defined mux list, or an antenna that doesn't reach that transmitter. Pick the list for the transmitter your antenna points at (step 4). - Muxes
OKbut no channels: the services are not mapped yet. Press Map all under Configuration → DVB Inputs → Services (step 5). - Freetvarr drops channels marked disabled in Configuration → Channel/EPG → Channels.
Empty guide
The TV Guide shows channels but no programmes, or only about a day of them.
- Without an XMLTV feed you get only what the broadcast signal carries. In Australia that is about a day of thin data. UK and European Freeview carry up to seven days over the air. Set up the feed (step 6).
- TVHeadend's log (
docker compose logs tvheadend) saysbroadcasts tot= 0: no feed channel is linked to a TVHeadend channel yet. In TVHeadend's web interface, link them under Configuration → Channel/EPG → EPG Grabber Channels, then press Re-run internal EPG grabbers. - With the feed loaded but one channel blank, that channel isn't linked to a feed channel. See Wrong programmes on a channel.
- After you install a grabber script, restart TVHeadend (
docker compose restart tvheadend). TVHeadend looks for grabbers at startup only, so a running TVHeadend never loads a new one. - Freetvarr keeps a copy of the TV guide for an hour, or a minute when it has no programmes. Freetvarr loads the TV guide again after guide setup and after a guide link change. After you fix TVHeadend, press
REFRESHon the TV Guide.
Wrong programmes on a channel
The TV Guide shows another channel's programmes on a channel, or no programmes on one channel while others have them. The channel is linked to the wrong guide channel, or to none.
- On the TV Guide, press
CHANNELS, press the pencil (Change guide source) next to the channel, pick the matching guide channel, then pressSAVE. See Channel listings. - Series recordings match on title and channel, so check the
UPCOMINGview after you change a link.
Missing channel logos
Freetvarr takes each channel's logo from TVHeadend's own channel icon first, then from the icon the XMLTV guide feed lists for that channel (the XMLTV <channel> <icon>). A channel with neither shows its name only.
- TVHeadend prefers picons, but none are installed: with picons preferred and no picon files, TVHeadend reports no icon for any channel. In TVHeadend's web interface, open Configuration → General → Base and untick the preference for picons, or install picons and set the picon path. Switch the view level to Expert if the picon fields are hidden.
- The feed icon doesn't load: feed icons are usually links to the internet, and the Freetvarr container fetches them itself. To check that the Freetvarr Docker container has outbound internet access, run
docker exec freetvarr node -e "fetch('https://example.com').then((r) => console.log(r.status))"in a terminal on the host (it outputs200when it does). - The Freetvarr user lacks Admin: TVHeadend serves the guide feed's channel list to admin users only, so the feed fallback finds no icons.
- The feed channel is unlinked: a feed icon only reaches a TVHeadend channel through the link in EPG Grabber Channels.
Missing programme images
Programme images come from the guide feed's <programme> <icon> entries. Over-the-air guide data carries none, and not every XMLTV feed includes them. A programme without an image shows its text only; nothing in Freetvarr needs fixing. The Freetvarr Docker container needs outbound internet access to fetch images from an external feed, as for channel logos.
Recordings an hour out after a clock change
Recordings on the days after a daylight-saving change start an hour early or late, often after a TVHeadend restart. The over-the-air EIT guide data of some broadcasters carries the wrong UTC offset after the change, and TVHeadend uses it until the XMLTV feed covers those dates. The author saw this in Sydney after 2026-10-04.
- In TVHeadend's web interface, press Re-run internal EPG grabbers under Configuration → Channel/EPG → EPG Grabber, then check the times in the Electronic Program Guide tab.
- Keep the XMLTV module at a higher priority than EIT (Guide priority).
Scheduled recordings vanished
Upcoming recordings from series recordings disappear after TVHeadend crashes or restarts, and return when the guide reloads. While the TV guide is empty, TVHeadend removes the scheduled entries of each autorec. With both of TVHeadend's guide save options off, the TV guide is empty after a restart.
- Turn on periodic save and save after import (Saving the guide).
- In TVHeadend's web interface, press Re-run internal EPG grabbers to reload the TV guide now (the series recordings schedule again from it).
Duplicate episode recordings
TVHeadend records the same episode twice in a row. The DVR profile's Re-record if errors setting is 10 by default, and a recording with more data errors than that schedules a repeat. Freetvarr shows the first recording as Recorded with a data-error warning, not as failed. In TVHeadend's DVR profile, set Re-record if errors to 0 (TVHeadend step 7).
Setup wizard keeps opening
TVHeadend's first-run wizard opens on every page load. The wizard value in Configuration → General → Base is still set because the wizard never finished. Open TVHeadend's first-run wizard and finish or cancel it, and the value clears (Securing by hand).
Unimported recordings
TVHeadend finished a recording, but nothing appears on the RECORDINGS tab or in your library.
- No series folder matches it. Freetvarr imports only recordings whose title contains the title of a series folder (Series). Press SERIES in the TV Guide, or use ADD TITLE in TITLE MATCHES.
- The folder is off. Scheduled syncs skip a series folder that is switched off.
- The sync hasn't run yet. The default SYNC SCHEDULE is
Every 30 minutes. PressSYNC NOWon the dashboard to run one at once. - It came in as SKIPPED or PARTIAL. See the next two sections.
Skipped recordings
The row's error on the RECORDINGS tab says which of the two causes it was. Press the row for the full error and steps to fix it.
- "file not found" or no filename: TVHeadend has no finished file yet. A recording in progress shows this, and post-recording padding can keep it here for up to ten minutes after the programme ends. The next sync picks it up.
- "outside the recordings mount": TVHeadend reported a path Freetvarr can't translate. The two recordings paths have to match. Press
CHECK TVHEADENDin SETTINGS, and see the two recordings paths.
Partial recordings
- The imported file came up more than
1MBshort of what TVHeadend reported. The next sync imports the file again. If it stays PARTIAL, the source itself is short. In TVHeadend's web interface, check the status of that entry (it usually reports data errors from a weak signal).
Replaced recordings
A recording shows REPLACED when its library file is gone and another file for the same episode is in its place. Freetvarr checks this at every sync and each time the RECORDINGS tab loads.
The usual cause is Sonarr. When Sonarr and Freetvarr save to the same TV library folder, Sonarr counts Freetvarr's recording as its own file for that episode. When Sonarr downloads a copy its quality profile rates higher, it moves Freetvarr's file to its recycle bin and keeps the download. The INFO panel of the recording names the file that replaced it.
Freetvarr leaves the replacement in place. To keep Freetvarr's recordings, open the series in Sonarr and turn off monitoring for the episodes Freetvarr records.
A recording shows NOT IN LIBRARY when its file is gone and nothing replaced it. Press IMPORT AGAIN on its row to import the TVHeadend copy again.
Slow imports
- A hardlink import is instant. If an import shows progress, Freetvarr is copying, because Freetvarr sees the recordings folder and the media library through separate mounts or on different disks. Put both under one mounted folder on one disk to import by hardlink (One shared mount).
Repeat recordings
TVHeadend records a repeat of an episode that Freetvarr already imported, and the next sync imports it again.
- The repeat has no episode number in the TV guide. Freetvarr's series recordings skip a repeat only when both airings carry the same season and episode number. Some free-to-air guides drop the number from daytime repeats. In TVHeadend's web interface, cancel that repeat in the Upcoming / Current Recordings tab.
- The kept entry is gone. With Remove after import on, TVHeadend keeps an entry for each imported episode in its Removed Recordings tab. Delete that entry and TVHeadend no longer knows the episode was recorded. The same happens when you press Remove on a finished recording in TVHeadend's own web interface while the DVR profile's Recording info retention period is
On file removal(the default).
TVHeadend crash on start
TVHeadend stops with a segfault (signal 11) just after it logs Purging obsolete autorec entries for current schedule.
- This is a TVHeadend bug: TVHeadend's cleanup of obsolete autorec entries reads freed memory after it drops a scheduled entry. Commit
5acec7ee5(2026-09-20) fixes it. Update TVHeadend to a build that includes it. - Back up TVHeadend's
/configfolder before you update the TVHeadend Docker image.
Permission errors
An import fails with a permission error, or the TVHeadend file won't delete.
- Set
PUID/PGIDto match the owner of the bind-mounted host folders, and use the same pair for both Docker containers. Freetvarr hardlinks and deletes files that TVHeadend created, so a mismatch fails at those steps.
Plex not refreshing
Episodes import, but Plex doesn't show them.
- Press
REFRESH PLEX NOWin SETTINGS. Freetvarr reportsPlex refresh sent (HTTP 200).or the error. Plex HTTP 401: the Plex token is wrong or expired. In SETTINGS, detect or paste the Plex token again (Plex).Plex HTTP 404: the section ID doesn't exist. In SETTINGS, pick the TV section again from the list.ECONNREFUSEDorECONNABORTED: the Plex URL is wrong, or Plex isn't running. Usehttp://<plex-host-ip>:32400.- The refresh succeeds but nothing appears: the Plex library doesn't include the folder Freetvarr writes to. Add the host folder
${DATA_PATH}/media/tvto the library (Plex).
Plex token auto-detect
- Auto-detect needs Plex's
Preferences.xmlinside the Freetvarr Docker container. Theplexprofile mounts it for you. For another Plex on the same host, setPLEX_PREFS_PATHin the.env. Plex lists where the file lives. - "Preferences.xml not found at /plex/Library/…": the
plexprofile is not running, andPLEX_PREFS_PATHis unset. Start the profile, or set the path in.env, then rundocker compose up -d freetvarr. - "Preferences.xml not found at /plex-preferences.xml":
PLEX_PREFS_PATHpoints at the wrong host file, so the mount is empty. Fix the path in.envand rundocker compose up -d freetvarr. - Or paste the Plex token into Settings yourself. Copy it from
app.plex.tv(or follow Plex's own support article on finding your token).
Container name lookups
Other containers can't reach Freetvarr by name.
- Under host networking, Freetvarr is on no Docker bridge network. Use the host's LAN IP and
FREETVARR_PORTinstead.
Ad detection errors
Ad detection is cutting the wrong things, or missing breaks.
- Ad detection is never perfect. Comskip's accuracy varies a lot by channel.
- Set the series to
DETECTmode first and check the break counts and minutes it reports on the RECORDINGS tab before switching toCUT. Allow about 30 minutes of scan per 75-minute recording on a home NAS. - Cuts snap to the nearest keyframe, so a second or two either side of a break is normal.
- To tune detection, place your own
comskip.iniin the/configbind mount. Your file overrides the bundled default, which the author tuned for Australian channels. Outside Australia, expect to tune your own. If a cut goes wrong, rename its<file>.ts.origbackup back to recover the original. See Ad removal.
Playback failed on HD channels
Chrome shows "Playback failed" or a black player on an HD channel, while SD channels play. Chrome cannot decode interlaced H.264, so Freetvarr must re-encode it. To check the method Freetvarr chose, run this command in a terminal in the freetvarr folder:
docker compose logs freetvarr | grep "\[live\] video"The line ends with the reason:
LIVE_TV_TRANSCODE=copy: H.264 passes through untouched. Remove the setting or set it toauto.not found; pass /dev/dri into the container: the container has no render device. Adddocker-compose.override.yml. Without it, Freetvarr uses software, which plays but costs much more CPU.permission denied for uid ...: the container user lacks the render group. SetRENDER_GIDin.envto the output ofstat -c %g /dev/dri/renderD128, then rundocker compose up -d freetvarrto recreate the Freetvarr Docker container.VAAPI test encode failed: ffmpeg's error follows the reason. The graphics chip or its driver does not support the encode. Freetvarr uses software.is not one of auto, hardware, software, copy:LIVE_TV_TRANSCODEhas a typo. Freetvarr uses software.
If the line says software and the channel stutters, the CPU is too slow for the software path. Choose a smaller stream or add hardware transcoding. See Video handling.
Missing captions
- Your broadcaster sends captions as Teletext or as DVB subtitles. Australian broadcasters send Teletext. Some players decode Teletext and some don't (it isn't a recording fault). See Captions in other apps.
- In Freetvarr's player, the CC button shows only on channels that carry Teletext subtitles, and some programmes have none. See Captions.
Chrome Live Caption
A black box titled Live Caption at the bottom of the Chrome window is Chrome's own speech-to-text, not Freetvarr's captions. Chrome makes the text from the sound of any video, so it can show words the broadcaster never sent. The Captions item in the video's menu can switch it on, but turning that item off later does not switch it off.
To switch it off:
- Open
chrome://settings/accessibilityin Chrome. - Turn off Live Caption.
Freetvarr's own captions show inside the picture. Press CC in the player to show or hide them.
Wrong timestamps
- Freetvarr uses the time zone you chose in the wizard. If Doctor warns that no zone is chosen and the system runs on
UTC, or that the zone is not a known one, choose your zone in SETTINGS, in the SCHEDULE panel. Freetvarr shows every time in that zone, on every device. - A
TZin your.envonly pre-fills the zone. The zone chosen in SETTINGS wins. IfTZis wrong and no zone is chosen, choose one in SETTINGS, or correctTZ(e.g.Australia/Sydney) and rundocker compose up -dto recreate the Docker containers. - TVHeadend follows the host clock's zone through its
/etc/localtimemount. SetTZin your.envto override it.
CSRF secret
- Exit on start with a message about
CONFIG_PATH: Freetvarr could not write itscsrf-secretfile. Check thatCONFIG_PATHis owned byPUID:PGID. - Reset the secret: delete
${CONFIG_PATH}/freetvarr/csrf-secretand restart Freetvarr (docker compose restart freetvarr). Freetvarr generates a new secret, and browsers get a fresh CSRF token automatically. Nothing else breaks.
Source install errors
Running Freetvarr from source (npm start) rather than in Docker fails at better-sqlite3.
- Freetvarr needs Node
24(package.jsonsetsengines), and the pinnedbetter-sqlite3ships prebuilt binaries for it. On a Node version with no prebuilt binary,npm run setupcompilesbetter-sqlite3from source, which needs Python 3,make, and a C++ compiler. Use Node 24 instead. Volta picks the pinned version up frompackage.json. See the deep dive.
Reporting a bug
Open an issue on GitHub with what you did, what you expected, and what happened. Include your versions: VERSIONS in SETTINGS → HELP lists the Freetvarr, TVHeadend, and Node versions and the UPTIME of Freetvarr (how long it has been running), and COPY puts them on the clipboard. It also says whether a newer Freetvarr release is out.