Downgrading Truenas Scale version

Hello all,

I was getting some errors in my TrueNAS installation so I decided to nuke it and install a clean version. When I tried to upload the configuration file I got the folowing error:

Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/middlewared/job.py", line 515, in run
    await self.future
  File "/usr/lib/python3/dist-packages/middlewared/job.py", line 562, in __run_body
    rv = await self.middleware.run_in_thread(self.method, *args)
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/middlewared/main.py", line 599, in run_in_thread
    return await self.run_in_executor(io_thread_pool_executor, method, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/middlewared/main.py", line 596, in run_in_executor
    return await loop.run_in_executor(pool, functools.partial(method, *args, **kwargs))
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/concurrent/futures/thread.py", line 58, in run
    result = self.fn(*self.args, **self.kwargs)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/middlewared/api/base/decorator.py", line 96, in wrapped
    result = func(*args)
             ^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/middlewared/plugins/config.py", line 113, in upload
    self.upload_impl(job, stf.name, is_tar_file=is_tar)
  File "/usr/lib/python3/dist-packages/middlewared/plugins/config.py", line 161, in upload_impl
    raise CallError(
middlewared.service_exception.CallError: [EFAULT] Uploaded TrueNAS database file is not valid:
+ DATABASE=/tmp/tmpgk2mog__/freenas-v1.db
+ PWENC_SECRET=/tmp/tmpgk2mog__/pwenc_secret
+ python3 -c import os; import sys; sys.path.remove("") if "" in sys.path else None; import middlewared; print(os.path.dirname(middlewared.__spec__.origin))
+ cd /usr/lib/python3/dist-packages/middlewared
+ FREENAS_DATABASE=/tmp/tmpgk2mog__/freenas-v1.db FREENAS_PWENC_SECRET=/tmp/tmpgk2mog__/pwenc_secret alembic upgrade head
INFO  [alembic.runtime.migration] Context impl SQLiteImpl.
INFO  [alembic.runtime.migration] Will assume non-transactional DDL.
Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/sqlalchemy/engine/base.py", line 1900, in _execute_context
    self.dialect.do_execute(
  File "/usr/lib/python3/dist-packages/sqlalchemy/engine/default.py", line 736, in do_execute
    cursor.execute(statement, parameters)
sqlite3.DatabaseError: database disk image is malformed

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/usr/bin/alembic", line 33, in <module>
    sys.exit(load_entry_point('alembic==1.8.1.dev0', 'console_scripts', 'alembic')())
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/alembic/config.py", line 590, in main
    CommandLine(prog=prog).main(argv=argv)
  File "/usr/lib/python3/dist-packages/alembic/config.py", line 584, in main
    self.run_cmd(cfg, options)
  File "/usr/lib/python3/dist-packages/alembic/config.py", line 561, in run_cmd
    fn(
  File "/usr/lib/python3/dist-packages/alembic/command.py", line 322, in upgrade
    script.run_env()
  File "/usr/lib/python3/dist-packages/alembic/script/base.py", line 569, in run_env
    util.load_python_file(self.dir, "env.py")
  File "/usr/lib/python3/dist-packages/alembic/util/pyfiles.py", line 94, in load_python_file
    module = load_module_py(module_id, path)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/alembic/util/pyfiles.py", line 110, in load_module_py
    spec.loader.exec_module(module)  # type: ignore
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<frozen importlib._bootstrap_external>", line 940, in exec_module
  File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
  File "/usr/lib/python3/dist-packages/middlewared/alembic/env.py", line 167, in <module>
    run_migrations_online()
  File "/usr/lib/python3/dist-packages/middlewared/alembic/env.py", line 161, in run_migrations_online
    context.run_migrations()
  File "<string>", line 8, in run_migrations
  File "/usr/lib/python3/dist-packages/alembic/runtime/environment.py", line 853, in run_migrations
    self.get_context().run_migrations(**kw)
  File "/usr/lib/python3/dist-packages/alembic/runtime/migration.py", line 601, in run_migrations
    heads = self.get_current_heads()
            ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/alembic/runtime/migration.py", line 533, in get_current_heads
    if not self._has_version_table():
           ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/alembic/runtime/migration.py", line 549, in _has_version_table
    return sqla_compat._connectable_has_table(
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/alembic/util/sqla_compat.py", line 200, in _connectable_has_table
    return inspect(connectable).has_table(tablename, schemaname)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/sqlalchemy/engine/reflection.py", line 283, in has_table
    return self.dialect.has_table(conn, table_name, schema)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/sqlalchemy/dialects/sqlite/base.py", line 2019, in has_table
    info = self._get_table_pragma(
           ^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/sqlalchemy/dialects/sqlite/base.py", line 2604, in _get_table_pragma
    cursor = connection.exec_driver_sql(statement)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/sqlalchemy/engine/base.py", line 1760, in exec_driver_sql
    return self._exec_driver_sql(
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/sqlalchemy/engine/base.py", line 1669, in _exec_driver_sql
    ret = self._execute_context(
          ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/sqlalchemy/engine/base.py", line 1943, in _execute_context
    self._handle_dbapi_exception(
  File "/usr/lib/python3/dist-packages/sqlalchemy/engine/base.py", line 2124, in _handle_dbapi_exception
    util.raise_(
  File "/usr/lib/python3/dist-packages/sqlalchemy/util/compat.py", line 211, in raise_
    raise exception
  File "/usr/lib/python3/dist-packages/sqlalchemy/engine/base.py", line 1900, in _execute_context
    self.dialect.do_execute(
  File "/usr/lib/python3/dist-packages/sqlalchemy/engine/default.py", line 736, in do_execute
    cursor.execute(statement, parameters)
sqlalchemy.exc.DatabaseError: (sqlite3.DatabaseError) database disk image is malformed
[SQL: PRAGMA main.table_info("alembic_version")]
(Background on this error at: https://sqlalche.me/e/14/4xp6)

My guess is that the last version available (And the one that I downloaded and installed) is 25.04.0, and my backup is from version 24.10.1.

The easiest thing would be to download version 24.10.1, however unfortunatelly I do not have easy access to my NAS right now, only remote, so I am trying to downgrade it via the web interface/command line.

So far I failed when I tried to ulpload the .update file of any previous version, getting the error:

Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/middlewared/job.py", line 515, in run
    await self.future
  File "/usr/lib/python3/dist-packages/middlewared/job.py", line 560, in __run_body
    rv = await self.method(*args)
         ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/middlewared/schema/processor.py", line 174, in nf
    return await func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/middlewared/plugins/update.py", line 441, in file
    await self.middleware.run_in_thread(self.file_impl, job, options)
  File "/usr/lib/python3/dist-packages/middlewared/main.py", line 599, in run_in_thread
    return await self.run_in_executor(io_thread_pool_executor, method, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/middlewared/main.py", line 596, in run_in_executor
    return await loop.run_in_executor(pool, functools.partial(method, *args, **kwargs))
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/concurrent/futures/thread.py", line 58, in run
    result = self.fn(*self.args, **self.kwargs)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/middlewared/plugins/update.py", line 411, in file_impl
    self.middleware.call_sync('update.install', job, destfile, update_options)
  File "/usr/lib/python3/dist-packages/middlewared/main.py", line 1013, in call_sync
    return methodobj(*prepared_call.args)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/middlewared/plugins/update_/install_linux.py", line 48, in install
    raise CallError(f'Unable to downgrade from {old_version} to {new_version}')
middlewared.service_exception.CallError: [EFAULT] Unable to downgrade from 25.04.0 to 24.10.0.1

So then my question would be: Is downgrading via WebUI even possible? Is the only way to nuke again the installation a make a clean install of 24.10.1 and then load the config file? Will it work and not report the first error if I upload the backup file in the same version that it was generated?

Thanks a lot in advance.

Historically if an upgrade didn’t go well I’d just select the boot environment from before the upgrade and be on my merry way.

Since this is a fresh installation unfortunatelly I dont have that option :confused:

The error message that your sqlite db disk image is malformed feels like it’s a corrupted backup. Do you have another one?

Have you checked your RAM and hardware lately? Seems like bad RAM or similar could cause both bad behavior and a corrupted backup.

Yess, it worked! The issue was the backup I guess. I tried installing an earlier one and now everything is normal. Thanks a lot!

Glad you actually had a backup!