This was my experience, too. I used the OliveTin "Create Native ADBTuner Channels + CDVR Custom Channels" action, including the "Native Remove" option for PBS, and it loaded both channels from the PBS json.
Thanks for the help!
This was my experience, too. I used the OliveTin "Create Native ADBTuner Channels + CDVR Custom Channels" action, including the "Native Remove" option for PBS, and it loaded both channels from the PBS json.
Thanks for the help!
I believe that OliveTin was using ADBTuner's API to add the channels one at a time which bypassed the validation (that was a bug on my end). The validation is now applied there as well but shouldn't be an issue since the package_name fields are also taken into consideration.
I'll give it a whirl later tonight to see since I got ESPN Unlimited, the true test can begin 
I'm trying to do a net new install to test this against, but keep running into this:
2026-07-28 15:00:12.570 | /app/.venv/bin/python: can't open file '/app/migrate.py': [Errno 2] No such file or directory
2026-07-28 15:00:12.985 | 2026/07/28 15:00:12 Starting proxy server with MPEG-TS null packet support
2026-07-28 15:00:12.985 | 2026/07/28 15:00:12 Loaded routes from file:
2026-07-28 15:00:12.985 |
2026-07-28 15:00:23.437 | 2026/07/28 15:00:23 [PROXY] Proxy error: dial tcp 127.0.0.1:5593: connect: connection refused
2026-07-28 15:00:31.578 | INFO: Started server process [10]
2026-07-28 15:00:31.579 | INFO: Waiting for application startup.
2026-07-28 15:00:31.587 | 2026-07-28 15:00:31.583 - server - ADBTuner 20260728-1
2026-07-28 15:00:31.587 | 2026-07-28 15:00:31.584 - schema_verification - Verifying database schema (/app/.config/config.db).
2026-07-28 15:00:31.810 | 2026-07-28 15:00:31.809 - server - Database schema verification was successful.
2026-07-28 15:00:32.158 | ERROR: Traceback (most recent call last):
2026-07-28 15:00:32.158 | File "/app/.venv/lib/python3.14/site-packages/sqlalchemy/engine/base.py", line 1969, in _exec_single_context
2026-07-28 15:00:32.158 | self.dialect.do_execute(
2026-07-28 15:00:32.158 | ~~~~~~~~~~~~~~~~~~~~~~~^
2026-07-28 15:00:32.158 | cursor, str_statement, effective_parameters, context
2026-07-28 15:00:32.158 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2026-07-28 15:00:32.158 | )
2026-07-28 15:00:32.158 | ^
2026-07-28 15:00:32.158 | File "/app/.venv/lib/python3.14/site-packages/sqlalchemy/engine/default.py", line 952, in do_execute
2026-07-28 15:00:32.158 | cursor.execute(statement, parameters)
2026-07-28 15:00:32.158 | ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^
2026-07-28 15:00:32.158 | sqlite3.OperationalError: no such table: app_settings
2026-07-28 15:00:32.158 |
2026-07-28 15:00:32.158 | The above exception was the direct cause of the following exception:
2026-07-28 15:00:32.158 |
2026-07-28 15:00:32.158 | Traceback (most recent call last):
2026-07-28 15:00:32.158 | File "/app/.venv/lib/python3.14/site-packages/starlette/routing.py", line 638, in lifespan
2026-07-28 15:00:32.158 | async with self.lifespan_context(app) as maybe_state:
2026-07-28 15:00:32.158 | ~~~~~~~~~~~~~~~~~~~~~^^^^^
2026-07-28 15:00:32.158 | File "/usr/local/lib/python3.14/contextlib.py", line 214, in __aenter__
2026-07-28 15:00:32.158 | return await anext(self.gen)
2026-07-28 15:00:32.158 | ^^^^^^^^^^^^^^^^^^^^^
2026-07-28 15:00:32.158 | File "/app/.venv/lib/python3.14/site-packages/fastapi/routing.py", line 216, in merged_lifespan
2026-07-28 15:00:32.158 | async with original_context(app) as maybe_original_state:
2026-07-28 15:00:32.158 | ~~~~~~~~~~~~~~~~^^^^^
2026-07-28 15:00:32.158 | File "/usr/local/lib/python3.14/contextlib.py", line 214, in __aenter__
2026-07-28 15:00:32.158 | return await anext(self.gen)
2026-07-28 15:00:32.158 | ^^^^^^^^^^^^^^^^^^^^^
2026-07-28 15:00:32.158 | File "/app/.venv/lib/python3.14/site-packages/fastapi/routing.py", line 216, in merged_lifespan
2026-07-28 15:00:32.158 | async with original_context(app) as maybe_original_state:
2026-07-28 15:00:32.158 | ~~~~~~~~~~~~~~~~^^^^^
2026-07-28 15:00:32.158 | File "/usr/local/lib/python3.14/contextlib.py", line 214, in __aenter__
2026-07-28 15:00:32.158 | return await anext(self.gen)
2026-07-28 15:00:32.158 | ^^^^^^^^^^^^^^^^^^^^^
2026-07-28 15:00:32.158 | File "/app/.venv/lib/python3.14/site-packages/fastapi/routing.py", line 216, in merged_lifespan
2026-07-28 15:00:32.158 | async with original_context(app) as maybe_original_state:
2026-07-28 15:00:32.158 | ~~~~~~~~~~~~~~~~^^^^^
2026-07-28 15:00:32.158 | File "/usr/local/lib/python3.14/contextlib.py", line 214, in __aenter__
2026-07-28 15:00:32.158 | return await anext(self.gen)
2026-07-28 15:00:32.158 | ^^^^^^^^^^^^^^^^^^^^^
2026-07-28 15:00:32.158 | File "/app/app/main.py", line 261, in lifespan
2026-07-28 15:00:32.158 | migrate_file_configurations()
2026-07-28 15:00:32.158 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~^^
2026-07-28 15:00:32.158 | File "/app/app/dependencies.py", line 532, in migrate_file_configurations
2026-07-28 15:00:32.158 | .first()
2026-07-28 15:00:32.158 | ~~~~~^^
2026-07-28 15:00:32.158 | File "/app/.venv/lib/python3.14/site-packages/sqlalchemy/orm/query.py", line 2766, in first
2026-07-28 15:00:32.158 | return self.limit(1)._iter().first() # type: ignore
2026-07-28 15:00:32.158 | ~~~~~~~~~~~~~~~~~~~^^
2026-07-28 15:00:32.158 | File "/app/.venv/lib/python3.14/site-packages/sqlalchemy/orm/query.py", line 2864, in _iter
2026-07-28 15:00:32.158 | result: Union[ScalarResult[_T], Result[_T]] = self.session.execute(
2026-07-28 15:00:32.158 | ~~~~~~~~~~~~~~~~~~~~^
2026-07-28 15:00:32.158 | statement,
2026-07-28 15:00:32.158 | ^^^^^^^^^^
2026-07-28 15:00:32.158 | params,
2026-07-28 15:00:32.158 | ^^^^^^^
2026-07-28 15:00:32.158 | execution_options={"_sa_orm_load_options": self.load_options},
2026-07-28 15:00:32.158 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2026-07-28 15:00:32.158 | )
2026-07-28 15:00:32.158 | ^
2026-07-28 15:00:32.158 | File "/app/.venv/lib/python3.14/site-packages/sqlalchemy/orm/session.py", line 2372, in execute
2026-07-28 15:00:32.158 | return self._execute_internal(
2026-07-28 15:00:32.158 | ~~~~~~~~~~~~~~~~~~~~~~^
2026-07-28 15:00:32.158 | statement,
2026-07-28 15:00:32.158 | ^^^^^^^^^^
2026-07-28 15:00:32.158 | ...<4 lines>...
2026-07-28 15:00:32.158 | _add_event=_add_event,
2026-07-28 15:00:32.158 | ^^^^^^^^^^^^^^^^^^^^^^
2026-07-28 15:00:32.158 | )
2026-07-28 15:00:32.158 | ^
2026-07-28 15:00:32.158 | File "/app/.venv/lib/python3.14/site-packages/sqlalchemy/orm/session.py", line 2270, in _execute_internal
2026-07-28 15:00:32.158 | result: Result[Any] = compile_state_cls.orm_execute_statement(
2026-07-28 15:00:32.158 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
2026-07-28 15:00:32.158 | self,
2026-07-28 15:00:32.158 | ^^^^^
2026-07-28 15:00:32.158 | ...<4 lines>...
2026-07-28 15:00:32.158 | conn,
2026-07-28 15:00:32.158 | ^^^^^
2026-07-28 15:00:32.158 | )
2026-07-28 15:00:32.158 | ^
2026-07-28 15:00:32.158 | File "/app/.venv/lib/python3.14/site-packages/sqlalchemy/orm/context.py", line 306, in orm_execute_statement
2026-07-28 15:00:32.158 | result = conn.execute(
2026-07-28 15:00:32.158 | statement, params or {}, execution_options=execution_options
2026-07-28 15:00:32.158 | )
2026-07-28 15:00:32.158 | File "/app/.venv/lib/python3.14/site-packages/sqlalchemy/engine/base.py", line 1421, in execute
2026-07-28 15:00:32.158 | return meth(
2026-07-28 15:00:32.158 | self,
2026-07-28 15:00:32.158 | distilled_parameters,
2026-07-28 15:00:32.158 | execution_options or NO_OPTIONS,
2026-07-28 15:00:32.158 | )
2026-07-28 15:00:32.158 | File "/app/.venv/lib/python3.14/site-packages/sqlalchemy/sql/elements.py", line 526, in _execute_on_connection
2026-07-28 15:00:32.158 | return connection._execute_clauseelement(
2026-07-28 15:00:32.158 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
2026-07-28 15:00:32.159 | self, distilled_params, execution_options
2026-07-28 15:00:32.159 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2026-07-28 15:00:32.159 | )
2026-07-28 15:00:32.159 | ^
2026-07-28 15:00:32.159 | File "/app/.venv/lib/python3.14/site-packages/sqlalchemy/engine/base.py", line 1643, in _execute_clauseelement
2026-07-28 15:00:32.159 | ret = self._execute_context(
2026-07-28 15:00:32.159 | dialect,
2026-07-28 15:00:32.159 | ...<8 lines>...
2026-07-28 15:00:32.159 | cache_hit=cache_hit,
2026-07-28 15:00:32.159 | )
2026-07-28 15:00:32.159 | File "/app/.venv/lib/python3.14/site-packages/sqlalchemy/engine/base.py", line 1848, in _execute_context
2026-07-28 15:00:32.159 | return self._exec_single_context(
2026-07-28 15:00:32.159 | ~~~~~~~~~~~~~~~~~~~~~~~~~^
2026-07-28 15:00:32.159 | dialect, context, statement, parameters
2026-07-28 15:00:32.159 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2026-07-28 15:00:32.159 | )
2026-07-28 15:00:32.159 | ^
2026-07-28 15:00:32.159 | File "/app/.venv/lib/python3.14/site-packages/sqlalchemy/engine/base.py", line 1988, in _exec_single_context
2026-07-28 15:00:32.159 | self._handle_dbapi_exception(
2026-07-28 15:00:32.159 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
2026-07-28 15:00:32.159 | e, str_statement, effective_parameters, cursor, context
2026-07-28 15:00:32.159 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2026-07-28 15:00:32.159 | )
2026-07-28 15:00:32.159 | ^
2026-07-28 15:00:32.159 | File "/app/.venv/lib/python3.14/site-packages/sqlalchemy/engine/base.py", line 2365, in _handle_dbapi_exception
2026-07-28 15:00:32.159 | raise sqlalchemy_exception.with_traceback(exc_info[2]) from e
2026-07-28 15:00:32.159 | File "/app/.venv/lib/python3.14/site-packages/sqlalchemy/engine/base.py", line 1969, in _exec_single_context
2026-07-28 15:00:32.159 | self.dialect.do_execute(
2026-07-28 15:00:32.159 | ~~~~~~~~~~~~~~~~~~~~~~~^
2026-07-28 15:00:32.159 | cursor, str_statement, effective_parameters, context
2026-07-28 15:00:32.159 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2026-07-28 15:00:32.159 | )
2026-07-28 15:00:32.159 | ^
2026-07-28 15:00:32.159 | File "/app/.venv/lib/python3.14/site-packages/sqlalchemy/engine/default.py", line 952, in do_execute
2026-07-28 15:00:32.159 | cursor.execute(statement, parameters)
2026-07-28 15:00:32.159 | ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^
2026-07-28 15:00:32.159 | sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) no such table: app_settings
2026-07-28 15:00:32.159 | [SQL: SELECT app_settings."key" AS app_settings_key, app_settings.value AS app_settings_value
2026-07-28 15:00:32.159 | FROM app_settings
2026-07-28 15:00:32.159 | WHERE app_settings."key" = ?
2026-07-28 15:00:32.159 | LIMIT ? OFFSET ?]
2026-07-28 15:00:32.159 | [parameters: ('configurations_migrated', 1, 0)]
2026-07-28 15:00:32.159 | (Background on this error at: https://sqlalche.me/e/20/e3q8)
2026-07-28 15:00:32.159 |
2026-07-28 15:00:32.162 | ERROR: Application startup failed. Exiting.
I even did an install against latest, confirmed that was working in general, and then changed to development, but still ended up there. This is not happening against my existing Container, which is functioning just fine:
So I cloned my data volume and pointed my net new install against that. With that, I was able to finally start:
2026-07-28 15:08:28.578 | /app/.venv/bin/python: can't open file '/app/migrate.py': [Errno 2] No such file or directory
2026-07-28 15:08:28.771 | 2026/07/28 15:08:28 Starting proxy server with MPEG-TS null packet support
2026-07-28 15:08:28.784 | 2026/07/28 15:08:28 Loaded routes from file:
2026-07-28 15:08:28.784 | "/proxy/1" -> "http://10.255.1.106:8090/hdmi1"
2026-07-28 15:08:29.849 | 2026/07/28 15:08:29 [PROXY] Proxy error: dial tcp 127.0.0.1:5593: connect: connection refused
2026-07-28 15:08:38.274 | INFO: Started server process [9]
2026-07-28 15:08:38.279 | 2026-07-28 15:08:38.278 - server - ADBTuner 20260728-1
2026-07-28 15:08:38.279 | 2026-07-28 15:08:38.278 - schema_verification - Verifying database schema (/app/.config/config.db).
2026-07-28 15:08:38.279 | INFO: Waiting for application startup.
2026-07-28 15:08:38.284 | 2026-07-28 15:08:38.284 - server - Database schema verification was successful.
2026-07-28 15:08:38.641 | 2026/07/28 15:08:38 Received updated routes, but no changes detected.
2026-07-28 15:08:38.676 | 2026-07-28 15:08:38.676 - tuner_management - Caching installed apps list for all tuners
2026-07-28 15:08:38.706 | 2026-07-28 15:08:38.706 - lib.controller_pool - Pool: creating controller for tuner 1 (10.255.1.168).
2026-07-28 15:08:38.708 | INFO: Application startup complete.
2026-07-28 15:08:38.783 | INFO: Uvicorn running on http://0.0.0.0:5593 (Press CTRL+C to quit)
And after getting going, I could confirm the import worked as expected, at least for all stations:

Thanks for this. I just pushed a new development build (20260728-2) in which you can actually start with a fresh database again. Oops.