Can't upgrade 25.10.0 on WRT32X

Hi there,

I have been using 25.10 since early January. Installed factory image from original Linksys image which I used to keep in its separate partition.

Everything went well and is still going well... however, no matter what method I try, I cannot install any newer version:

  1. Seems like 25.10 no longer exposes the boot_part FW variable, so I haven't been able to boot back to Linksys FW to install 25.10.1/2 from scratch
  2. Attended sysupgrade method fails with the following error
Traceback (most recent call last):
  File "/app/.venv/lib/python3.14/site-packages/rq/worker/base.py", line 1463, in perform_job
    return_value = job.perform()
  File "/app/.venv/lib/python3.14/site-packages/rq/job.py", line 1318, in perform
    self._result = self._execute()
                   ~~~~~~~~~~~~~^^
  File "/app/.venv/lib/python3.14/site-packages/rq/job.py", line 1378, in _execute
    result = self.func(*self.args, **self.kwargs)
  File "/app/asu/build.py", line 489, in build
    result = _build(build_request, job)
  File "/app/asu/build.py", line 75, in _build
    bin_dir.mkdir(parents=True, exist_ok=True)
    ~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/root/.local/share/uv/python/cpython-3.14.3-linux-x86_64-gnu/lib/python3.14/pathlib/__init__.py", line 1011, in mkdir
    os.mkdir(self, mode)
    ~~~~~~~~^^^^^^^^^^^^
OSError: [Errno 28] No space left on device: '/srv/store/cd1f6697f05657a267cd12aab2af7d06a361e8452eacb384b36bc9c0abb3426a'

However, there should not be anything installed over the factory image (used to have OpenVPN/Wireguard on 24.x, but wiped that out when installing 25.10). Output for df command below:

Filesystem           1K-blocks      Used Available Use% Mounted on
/dev/root                 5376      5376         0 100% /rom
tmpfs                   253436      1892    251544   1% /tmp
/dev/ubi0_1              95304        76     90392   0% /overlay
overlayfs:/overlay       95304        76     90392   0% /
tmpfs                      512         0       512   0% /dev
  1. When installing a downloaded squashfs image downloaded from OpenWRT.com, after uploaded and a somewhat longer than usual wait, the router reboots back to 25.10.0 (guessing that installation over the second parition failed and router reverted to last good configuration?)

I know the WRT32X is ancient but for my use, it really does the job well. Have another somewhat newer (Qualcomm based) router that I could try, but was wondering if anyone still using Linksys routers have faced (and solved) this issue already,

Best regards,
JP

The ASU server is having sporadic disk space issues. You can keep trying every few hours and see if you can get it to work...

1 Like

Yeah, tried again and this time the attended sysupgrade generated the build...

However, same behavior when trying to install a manually downloaded one from www.openwrt.org...

Once it comes out of the reboot phase, the installed software is still 25.10.0.

Any logs I can gather to help debugging?

Best regards,
JP

If you have Adguard this may apply to you.

https://forum.openwrt.org/t/adblock-support-thread/507/3426?u=newsense

If you need to apply this fix try to update again after applying the fix.

Logs are all in RAM by default, plus the sysupgrade tool kills all processes (including logging) as part of the installation, so it's not possible to see what's going on. We might be able to get some output by turning on shell tracing (and although that will die when stdout goes away, it may tell us something).

Get an image that fails into /tmp/firmware.bin, look at its metadata, then run sysupgrade with shell tracing on.

$ owut download
# or if that fails 
# wget -O /tmp/firmware.bin https://downloads...

$ fwtool -i - /tmp/firmware.bin
{ "metadata_version": 1.1, ...
# Copy the above output before you proceed.

$ sh -x /sbin/sysupgrade /tmp/firmware.bin
+ . /lib/functions.sh
+ N='
'
+ _C=0
+ NO_EXPORT=1
+ LOAD_STATE=1
... for 1000s of lines of output ...

We're interested in the last 30-40 lines, as that's most likely to show the error message.

Midway I got:

{  "metadata_version": "1.1", "compat_version": "2.0", "compat_message": "Partition design has changed compared to older versions (up to 19.07) due to kernel size restrictions. Upgrade via sysupgrade mechanism is not possible, so new installation via factory style image is required.", "new_supported_devices": ["linksys,wrt32x","armada-385-linksys-venom","linksys,venom"], "supported_devices": ["linksys,wrt32x armada-385-linksys-venom linksys,venom - Image version mismatch: image 2.0, device 1.0. Please wipe config during upgrade (force required) or reinstall. Reason: Partition design has changed compared to older versions (up to 19.07) due to kernel size restrictions. Upgrade via sysupgrade mechanism is not possible, so new installation via factory style image is required."],  "version": { "dist": "OpenWrt", "version": "25.12.2", "revision": "r32802-f505120278", "target": "mvebu/cortexa9", "board": "armada-385-linksys-venom" } }

So I guess no sysupgrades possible with this system?

In any case, blindly attempting the upgrade yields:

+ __tar_print_padding 183
+ dd 'if=/dev/zero' 'bs=1' 'count=183'
+ printf '%s' '
exit 0'
+ __tar_print_padding 505
+ dd 'if=/dev/zero' 'bs=1' 'count=505'
+ '[' 0 -eq 0 ]
+ '[' 0 -eq 1 ]
+ '[' 0 -eq 0 ]
+ tar c -C / -T /tmp/sysupgrade.conffiles
+ '[' 0 -eq 0 ]
+ err=0
+ set +o pipefail
+ '[' 0 -ne 0 ]
+ rm -f /tmp/sysupgrade.conffiles
+ return 0
+ export 'SAVE_CONFIG=1'
+ '[' 0 -eq 1 ]
+ install_bin /sbin/upgraded
+ local src files
+ src=/sbin/upgraded
+ files=/sbin/upgraded
+ '[' -x /sbin/upgraded ]
+ libs /sbin/upgraded
+ + sed -E 's/(.* => )?(.*) .*/\2/'
ldd /sbin/upgraded
+ files='/sbin/upgraded         /lib/ld-musl-armhf.so.1
/lib/libubox.so.20260213
/lib/libgcc_s.so.1
/lib/ld-musl-armhf.so.1'
+ install_file /sbin/upgraded /lib/ld-musl-armhf.so.1 /lib/libubox.so.20260213 /lib/libgcc_s.so.1 /lib/ld-musl-armhf.so.1
+ local target dest dir
+ '[' -L /sbin/upgraded ]
+ dest=/tmp/root//sbin/upgraded
+ '[' -f /sbin/upgraded -a '!' -f /tmp/root//sbin/upgraded ]
+ dirname /tmp/root//sbin/upgraded
+ dir=/tmp/root//sbin
+ mkdir -p /tmp/root//sbin
+ cp /sbin/upgraded /tmp/root//sbin/upgraded
+ '[' -L /lib/ld-musl-armhf.so.1 ]
+ readlink -f /lib/ld-musl-armhf.so.1
+ target=/lib/libc.so
+ dest=/tmp/root//lib/ld-musl-armhf.so.1
+ '[' '!' -f /tmp/root//lib/ld-musl-armhf.so.1 ]
+ dirname /tmp/root//lib/ld-musl-armhf.so.1
+ dir=/tmp/root//lib
+ mkdir -p /tmp/root//lib
+ ln -s /lib/libc.so /tmp/root//lib/ld-musl-armhf.so.1
+ file=/lib/libc.so
+ dest=/tmp/root//lib/libc.so
+ '[' -f /lib/libc.so -a '!' -f /tmp/root//lib/libc.so ]
+ dirname /tmp/root//lib/libc.so
+ dir=/tmp/root//lib
+ mkdir -p /tmp/root//lib
+ cp /lib/libc.so /tmp/root//lib/libc.so
+ '[' -L /lib/libubox.so.20260213 ]
+ dest=/tmp/root//lib/libubox.so.20260213
+ '[' -f /lib/libubox.so.20260213 -a '!' -f /tmp/root//lib/libubox.so.20260213 ]
+ dirname /tmp/root//lib/libubox.so.20260213
+ dir=/tmp/root//lib
+ mkdir -p /tmp/root//lib
+ cp /lib/libubox.so.20260213 /tmp/root//lib/libubox.so.20260213
+ '[' -L /lib/libgcc_s.so.1 ]
+ dest=/tmp/root//lib/libgcc_s.so.1
+ '[' -f /lib/libgcc_s.so.1 -a '!' -f /tmp/root//lib/libgcc_s.so.1 ]
+ dirname /tmp/root//lib/libgcc_s.so.1
+ dir=/tmp/root//lib
+ mkdir -p /tmp/root//lib
+ cp /lib/libgcc_s.so.1 /tmp/root//lib/libgcc_s.so.1
+ '[' -L /lib/ld-musl-armhf.so.1 ]
+ readlink -f /lib/ld-musl-armhf.so.1
+ target=/lib/libc.so
+ dest=/tmp/root//lib/ld-musl-armhf.so.1
+ '[' '!' -f /tmp/root//lib/ld-musl-armhf.so.1 ]
+ file=/lib/libc.so
+ dest=/tmp/root//lib/libc.so
+ '[' -f /lib/libc.so -a '!' -f /tmp/root//lib/libc.so ]
+ v 'Commencing upgrade. Closing all shell sessions.'
+ date
+ _v 'Sun Apr  5 15:31:22 GMT 2026 upgrade: Commencing upgrade. Closing all shell sessions.'
+ '[' -n 1 ]
+ '[' 1 -ge 1 ]
+ echo 'Sun Apr  5 15:31:22 GMT 2026 upgrade: Commencing upgrade. Closing all shell sessions.'
Sun Apr  5 15:31:22 GMT 2026 upgrade: Commencing upgrade. Closing all shell sessions.
+ logger -p info -t upgrade 'Commencing upgrade. Closing all shell sessions.'
+ '[' -n  ]
+ json_init
+ json_cleanup
+ local unset tmp
+ _json_get_var unset JSON_UNSET
+ eval 'unset="$JSON_UNSET"'
+ unset='J_T1 J_V_tests J_T1_fwtool_signature J_T1_fwtool_device_match J_V_valid J_V_forceable J_V_allow_backup'
+ unset U_J_T1 K_J_T1 S_J_T1 T_J_T1 N_J_T1 J_T1
+ unset U_J_V_tests K_J_V_tests S_J_V_tests T_J_V_tests N_J_V_tests J_V_tests
+ unset U_J_T1_fwtool_signature K_J_T1_fwtool_signature S_J_T1_fwtool_signature T_J_T1_fwtool_signature N_J_T1_fwtool_signature J_T1_fwtool_signature
+ unset U_J_T1_fwtool_device_match K_J_T1_fwtool_device_match S_J_T1_fwtool_device_match T_J_T1_fwtool_device_match N_J_T1_fwtool_device_match J_T1_fwtool_device_match
+ unset U_J_V_valid K_J_V_valid S_J_V_valid T_J_V_valid N_J_V_valid J_V_valid
+ unset U_J_V_forceable K_J_V_forceable S_J_V_forceable T_J_V_forceable N_J_V_forceable J_V_forceable
+ unset U_J_V_allow_backup K_J_V_allow_backup S_J_V_allow_backup T_J_V_allow_backup N_J_V_allow_backup J_V_allow_backup
+ unset U_J_V K_J_V S_J_V T_J_V N_J_V J_V
+ unset JSON_SEQ JSON_CUR JSON_UNSET
+ export -n 'JSON_SEQ=0'
+ export -- 'JSON_CUR=J_V' 'K_J_V='
+ json_add_string prefix /tmp/root
+ local cur
+ _json_get_var cur JSON_CUR
+ eval 'cur="$JSON_CUR"'
+ cur=J_V
+ _json_add_generic string prefix /tmp/root J_V
+ local var
+ '[' J_V '=' J_A ]
+ var=prefix
+ '[[' prefix '==' prefix ]]
+ export -- 'J_V_prefix=/tmp/root' 'T_J_V_prefix=string'
+ _jshn_append JSON_UNSET J_V_prefix
+ local '_a_value=J_V_prefix'
+ eval 'JSON_UNSET="${JSON_UNSET}${JSON_UNSET:+ }$_a_value"'
+ JSON_UNSET=J_V_prefix
+ _jshn_append K_J_V prefix
+ local '_a_value=prefix'
+ eval 'K_J_V="${K_J_V}${K_J_V:+ }$_a_value"'
+ K_J_V=prefix
+ json_add_string path /tmp/firmware.bin
+ local cur
+ _json_get_var cur JSON_CUR
+ eval 'cur="$JSON_CUR"'
+ cur=J_V
+ _json_add_generic string path /tmp/firmware.bin J_V
+ local var
+ '[' J_V '=' J_A ]
+ var=path
+ '[[' path '==' path ]]
+ export -- 'J_V_path=/tmp/firmware.bin' 'T_J_V_path=string'
+ _jshn_append JSON_UNSET J_V_path
+ local '_a_value=J_V_path'
+ eval 'JSON_UNSET="${JSON_UNSET}${JSON_UNSET:+ }$_a_value"'
+ JSON_UNSET='J_V_prefix J_V_path'
+ _jshn_append K_J_V path
+ local '_a_value=path'
+ eval 'K_J_V="${K_J_V}${K_J_V:+ }$_a_value"'
+ K_J_V='prefix path'
+ '[' 0 -eq 1 ]
+ '[' 1 -eq 1 ]
+ json_add_string backup /tmp/sysupgrade.tgz
+ local cur
+ _json_get_var cur JSON_CUR
+ eval 'cur="$JSON_CUR"'
+ cur=J_V
+ _json_add_generic string backup /tmp/sysupgrade.tgz J_V
+ local var
+ '[' J_V '=' J_A ]
+ var=backup
+ '[[' backup '==' backup ]]
+ export -- 'J_V_backup=/tmp/sysupgrade.tgz' 'T_J_V_backup=string'
+ _jshn_append JSON_UNSET J_V_backup
+ local '_a_value=J_V_backup'
+ eval 'JSON_UNSET="${JSON_UNSET}${JSON_UNSET:+ }$_a_value"'
+ JSON_UNSET='J_V_prefix J_V_path J_V_backup'
+ _jshn_append K_J_V backup
+ local '_a_value=backup'
+ eval 'K_J_V="${K_J_V}${K_J_V:+ }$_a_value"'
+ K_J_V='prefix path backup'
+ json_add_string command /lib/upgrade/do_stage2
+ local cur
+ _json_get_var cur JSON_CUR
+ eval 'cur="$JSON_CUR"'
+ cur=J_V
+ _json_add_generic string command /lib/upgrade/do_stage2 J_V
+ local var
+ '[' J_V '=' J_A ]
+ var=command
+ '[[' command '==' command ]]
+ export -- 'J_V_command=/lib/upgrade/do_stage2' 'T_J_V_command=string'
+ _jshn_append JSON_UNSET J_V_command
+ local '_a_value=J_V_command'
+ eval 'JSON_UNSET="${JSON_UNSET}${JSON_UNSET:+ }$_a_value"'
+ JSON_UNSET='J_V_prefix J_V_path J_V_backup J_V_command'
+ _jshn_append K_J_V command
+ local '_a_value=command'
+ eval 'K_J_V="${K_J_V}${K_J_V:+ }$_a_value"'
+ K_J_V='prefix path backup command'
+ json_add_object options
+ _json_add_table options object T
+ local cur seq
+ _json_get_var cur JSON_CUR
+ eval 'cur="$JSON_CUR"'
+ cur=J_V
+ _json_inc JSON_SEQ seq
+ let 'JSON_SEQ += 1' 'seq = JSON_SEQ'
+ local 'table=J_T1'
+ _json_set_var U_J_T1 J_V
+ local '___val=J_V'
+ eval 'U_J_T1="$___val"'
+ U_J_T1=J_V
+ export -- 'K_J_T1='
+ unset S_J_T1
+ _json_set_var JSON_CUR J_T1
+ local '___val=J_T1'
+ eval 'JSON_CUR="$___val"'
+ JSON_CUR=J_T1
+ _jshn_append JSON_UNSET J_T1
+ local '_a_value=J_T1'
+ eval 'JSON_UNSET="${JSON_UNSET}${JSON_UNSET:+ }$_a_value"'
+ JSON_UNSET='J_V_prefix J_V_path J_V_backup J_V_command J_T1'
+ _json_add_generic object options J_T1 J_V
+ local var
+ '[' J_V '=' J_A ]
+ var=options
+ '[[' options '==' options ]]
+ export -- 'J_V_options=J_T1' 'T_J_V_options=object'
+ _jshn_append JSON_UNSET J_V_options
+ local '_a_value=J_V_options'
+ eval 'JSON_UNSET="${JSON_UNSET}${JSON_UNSET:+ }$_a_value"'
+ JSON_UNSET='J_V_prefix J_V_path J_V_backup J_V_command J_T1 J_V_options'
+ _jshn_append K_J_V options
+ local '_a_value=options'
+ eval 'K_J_V="${K_J_V}${K_J_V:+ }$_a_value"'
+ K_J_V='prefix path backup command options'
+ json_add_int save_partitions 1
+ local cur
+ _json_get_var cur JSON_CUR
+ eval 'cur="$JSON_CUR"'
+ cur=J_T1
+ _json_add_generic int save_partitions 1 J_T1
+ local var
+ '[' J_T '=' J_A ]
+ var=save_partitions
+ '[[' save_partitions '==' save_partitions ]]
+ export -- 'J_T1_save_partitions=1' 'T_J_T1_save_partitions=int'
+ _jshn_append JSON_UNSET J_T1_save_partitions
+ local '_a_value=J_T1_save_partitions'
+ eval 'JSON_UNSET="${JSON_UNSET}${JSON_UNSET:+ }$_a_value"'
+ JSON_UNSET='J_V_prefix J_V_path J_V_backup J_V_command J_T1 J_V_options J_T1_save_partitions'
+ _jshn_append K_J_T1 save_partitions
+ local '_a_value=save_partitions'
+ eval 'K_J_T1="${K_J_T1}${K_J_T1:+ }$_a_value"'
+ K_J_T1=save_partitions
+ json_add_int add_provisioning 0
+ local cur
+ _json_get_var cur JSON_CUR
+ eval 'cur="$JSON_CUR"'
+ cur=J_T1
+ _json_add_generic int add_provisioning 0 J_T1
+ local var
+ '[' J_T '=' J_A ]
+ var=add_provisioning
+ '[[' add_provisioning '==' add_provisioning ]]
+ export -- 'J_T1_add_provisioning=0' 'T_J_T1_add_provisioning=int'
+ _jshn_append JSON_UNSET J_T1_add_provisioning
+ local '_a_value=J_T1_add_provisioning'
+ eval 'JSON_UNSET="${JSON_UNSET}${JSON_UNSET:+ }$_a_value"'
+ JSON_UNSET='J_V_prefix J_V_path J_V_backup J_V_command J_T1 J_V_options J_T1_save_partitions J_T1_add_provisioning'
+ _jshn_append K_J_T1 add_provisioning
+ local '_a_value=add_provisioning'
+ eval 'K_J_T1="${K_J_T1}${K_J_T1:+ }$_a_value"'
+ K_J_T1='save_partitions add_provisioning'
+ '[' 0 -eq 1 ]
+ json_close_object
+ _json_close_table
+ local _s_cur
+ _json_get_var _s_cur JSON_CUR
+ eval '_s_cur="$JSON_CUR"'
+ _s_cur=J_T1
+ _json_get_var JSON_CUR U_J_T1
+ eval 'JSON_CUR="$U_J_T1"'
+ JSON_CUR=J_V
+ json_dump
+ jshn -w
+ ubus call system sysupgrade '{ "prefix": "\/tmp\/root", "path": "\/tmp\/firmware.bin", "backup": "\/tmp\/sysupgrade.tgz", "command": "\/lib\/upgrade\/do_stage2", "options": { "save_partitions": 1, "add_provisioning": 0 } }'

That is basically the complete log after the checksum is computed... nothing jumping out at me, but, nothing would anyways...

Seen the log from the firware tool, I will attemp a factory install.

That's a one-time thing, sysupgrade can't handle this specific upgrade because it requires concurrent partition editing and so on. You'll need to consult the wiki page for your device to see what you need to do to convert to the new partition design. Once you've done that, sysupgrade should start working again for future upgrades.

Yeah, that's the step where everything gets shut down so as not to interfere with deleting the old image and packages et cetera. Everything looks ok up to that point, then it enters the black hole.

:man_shrugging:

Flashing factory on top also failed... at least it came back to 25.12.0 still being functional.

I guess I will have to flash old WRT32X firmware prior to any update, and perform a factory install over that one...

Not ideal, but anyways...

UPDATE: no, it won't take Linksys firmware either... always back to 25.12.0

Will try to force a boot to the second partition (not even sure that is still a thing in 25.12 and see if whatever is there is healthy enough...

Ok. final post on this topic...

Managed to move to 25.12.2 by doing the following:

  1. Backup router configuration to zip
  2. Boot from 2nd partition where I have the original Linksys firmware
  3. Install factory image from Linksys firmware
  4. Restore the configuration backup

To boot into the second partition I went to Software, updated packages and installed luci-app-advance-reboot, which surprisingly worked for me...

I say surprisingly because I had expected the previous failed upgraded to have messed up the second partition, but luckily it wasn't.

Normally I would do the boot partition switch using fw_printenv and fw_setenv on the boot_part uboot variable, but I could not find that one once I migrated to 25.12... I guess the maintainers of the luci app know the new method.

Maybe in the future a sysupgrade is possible again, but for the time being I have a workaround that works for me (besides, l personally like to keep the old Linksys partition there just in case, only reason I tried sysupgrade this time is because I could not switch boot partitions in the way I was used to).

Best regards,
JP

Yeah, from the message in the metadata it sounded pretty ominous...

Glad you got it sorted! :+1:t3:

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.