中文 English

[Clickbait Alert] Switching to a Chinese Mirror Nearly Broke My Ubuntu: A Real Story of apt Dependency Hell

Published: 2026-05-17
Ubuntu apt mirror source dependency conflict Huawei Cloud NetEase Aliyun troubleshooting

TL;DR

I switched to a domestic Chinese mirror for Ubuntu and thought it would take 10 minutes. It took two hours. This article documents the entire journey from “mirror sync delay causing version mismatch” to “dpkg forced downgrade” to “apt fully restored.” The core lesson: switching a mirror is not a one-click fix—version consistency is everything. If you swap mirrors on a system that’s been running for months, you have a 99% chance of hitting dependency conflicts.

All operations in this article are based on Ubuntu 26.04 (Plucky). All IPs, hostnames, and paths are sanitized examples and contain no internal network addresses or sensitive information.

Switching mirrors feels good until dependencies explode

Figure 1: Before vs after switching mirrors — what you expect vs what actually happens

0. Background: Why Switch Mirrors?

The story starts simply: a freshly deployed Ubuntu 26.04 server needed basic tools like vim, curl, and wget installed. The server was on an internal network, so accessing overseas apt sources was painfully slow—hence the plan to switch to a domestic Chinese mirror.

First, let’s check the current apt source configuration:

cat /etc/apt/sources.list.d/ubuntu.sources

The output:

Types: deb
URIs: http://archive.ubuntu.com/ubuntu/
Suites: resolute resolute-updates resolute-backports
Components: main restricted universe multiverse
Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg

Types: deb
URIs: http://security.ubuntu.com/ubuntu/
Suites: resolute-security
Components: main restricted universe multiverse
Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg

Seeing resolute gave me pause—this is the codename for Ubuntu 25.04, but the machine clearly has Ubuntu 26.04 installed. Ubuntu 26.04’s codename is Plucky (the 16th letter of the alphabet). It appears the default apt source configuration for Ubuntu 26.04 had the wrong codename, which is why it’s crucial to verify the Suites field when switching mirrors.

The natural reaction was to swap in a domestic mirror—Huawei Cloud, Aliyun, and NetEase were all tried in succession. Initial tests looked fine: apt update successfully fetched the package lists. Then I ran the installation:

apt install vim lrzsz p7zip unzip net-tools curl wget ncdu -y

And immediately hit an error:

Unsatisfied dependencies:
  curl : Depends: libcurl4t64 (= 8.12.1-3ubuntu1) but 8.18.0-1ubuntu2 is to be installed
  vim : Depends: vim-common (= 2:9.1.0967-1ubuntu4.1) but 2:9.1.2141-1ubuntu4 is to be installed
        Depends: vim-runtime (= 2:9.1.0967-1ubuntu4.1) but it is not going to be installed
        Depends: libpython3.13 (>= 3.13.0~rc3) but it is not going to be installed

The error message was unambiguous: the locally installed package versions don’t match what’s available in the mirror. The local system had newer versions, but the mirror only had older ones. apt was trapped in a deadlock: “install a new package that requires an old library.”

The dependency conflict error

Figure 2: apt’s dependency error — the red box highlights the core conflict

1. Problem Analysis: Why Does Switching Mirrors Cause Dependency Conflicts?

1.1 Root Cause: Mirror Sync Delay + System Version Fragmentation

The problem stems from the local package version on the system being out of sync with the mirror:

When apt tries to install vim:

The same issue occurs between curl and libcurl4t64.

1.2 Why This Happens: Local State vs. Mirror Version Fragmentation

Check the current state:

apt-cache policy vim vim-common curl libcurl4t64

Output:

vim:
  Installed: (none)
  Candidate: 2:9.1.0967-1ubuntu4.1
  Version table:
     2:9.1.0967-1ubuntu4.1 500 <- mirror
     2:9.1.0967-1ubuntu4 500

vim-common:
  Installed: 2:9.1.2141-1ubuntu4  <- local version is newer than mirror!
  Candidate: 2:9.1.2141-1ubuntu4
  Version table:
     2:9.1.0967-1ubuntu4.1 500
     2:9.1.0967-1ubuntu4 500

libcurl4t64:
  Installed: 8.18.0-1ubuntu2  <- local version
  Candidate: 8.18.0-1ubuntu2
  Version table:
     8.12.1-3ubuntu1 500  <- mirror has older version

The core issue: the Candidate (candidate version) comes from the mirror, but dpkg already considers the local version “correct.” When apt performs dependency resolution, the two sides don’t match, creating a deadlock.

1.3 Why Do Domestic Mirrors Get Out of Sync?

Many ask: aren’t mirrors synced in real time? Why would there be a version difference?

Several situations cause this:

Cause Explanation
Scheduled batch sync Most domestic mirrors use rsync on a schedule (daily/hourly), not real-time push
Staged sync Some mirrors sync by component in stages (main first, security later)
Sync chain delay The path from official Ubuntu sources to domestic mirrors inherently has hours of delay
Local manual installation The sysadmin manually installed a newer package than the mirror has (compilation, direct deb)

For this server, it was likely that the system’s pre-installed packages were newer than any domestic mirror—Ubuntu 26.04 launched in April 2026, and our system may have received packages pushed shortly after the launch, before domestic mirrors had synced.

1.4 When to Switch Mirrors

Strongly recommended at these times:

  1. Immediately after a fresh install, then run apt update && apt upgrade -y for a full upgrade
  2. Right after the system is deployed, before any additional software is installed
  3. Before building Docker images, specifying the mirror directly in the Dockerfile

Avoid:

  1. A system that’s been running for a while with manual installations/updates
  2. Production environments already running business workloads
  3. Systems that have already obtained packages newer than the mirror through other channels

If your system is already in a “fragmented” state, the full fix is to full-upgrade or full-downgrade to a consistent version with the mirror, or use the workaround in this article.

2. Resolution Process: From Failure to Success

2.1 Step 1: Standard Fix Attempts (Failed)

# Clean apt cache
apt clean
apt update

# Try to fix dependencies
apt --fix-broken install -y

Result: No improvement. Dependency issues persisted.

2.2 Step 2: Individual Package Installation Test (Discovered Which Work and Which Don’t)

# Install one at a time to see which succeed
for pkg in vim lrzsz p7zip unzip net-tools curl wget ncdu; do
    echo "=== Installing $pkg ==="
    apt install $pkg -y 2>&1 | tail -5
done

Results:

Package Result Notes
lrzsz ✅ Success No dependency conflict
p7zip ✅ Success No dependency conflict
unzip ✅ Success Already latest
net-tools ✅ Success No dependency conflict
wget ✅ Success Already latest
ncdu ✅ Success No dependency conflict
vim ❌ Failed vim-common version mismatch
curl ❌ Failed libcurl4t64 version mismatch

This revealed that the issue was concentrated on vim and curl—all other packages had no conflicts.

2.3 Step 3: Understanding the Relationship Between dpkg and apt

After digging deeper, I understood the root cause:

So when vim needs vim-common = 9.1.0967-1ubuntu4.1 but locally has vim-common = 9.1.2141-1ubuntu4:

Key insight: the solution isn’t to have apt upgrade—it’s to force the mirror’s version to replace the local version.

2.4 Step 4: Full Upgrade Attempt (Partial Success)

apt full-upgrade -y

This command is more aggressive than apt upgrade—it attempts to install/upgrade/remove packages as needed to resolve dependencies.

Result: The system upgraded 3 packages (libicu76, libxml2, tracker-extract), removed localsearch, but the vim and curl issues remained.

2.5 Step 5: Manual deb Package Download and Forced Installation (Key Breakthrough)

The core approach: bypass apt’s dependency resolution and directly use dpkg to force-install the correct versions.

5.1 Remove Conflicting Local Packages

First, force-remove the incompatible local packages with dpkg --force-all:

# Force remove vim-common (note: this also removes vim-tiny which depends on it)
dpkg --force-all --remove vim-common

Output:

dpkg: vim-common: dependency problems, but removing anyway as you requested:
 vim-tiny depends on vim-common (= 2:9.1.2141-1ubuntu4).
Removing vim-common (2:9.1.2141-1ubuntu4)…

Successfully removed the local vim-common. Note the use of --force-all—normally dpkg wouldn’t allow removing a package that other packages depend on.

5.2 Download the Correct Versions

Download the needed packages into a temp directory:

mkdir -p /tmp/vim-packages
cd /tmp/vim-packages
apt download vim-common vim-runtime vim

apt download is a useful command—it only downloads the deb package without installing. It’s more reliable than wget (since URL paths vary by version).

After downloading:

vim_2:9.1.0967-1ubuntu4.1_amd64.deb
vim-common_2:9.1.0967-1ubuntu4.1_all.deb
vim-runtime_2:9.1.0967-1ubuntu4.1_all.deb

5.3 Forced Installation

dpkg -i vim-common_*.deb vim-runtime_*.deb vim_*.deb

The installation reported an error:

Package libpython3.13 is not installed.
dpkg: error processing package vim (--install):
 dependency problems - leaving unconfigured

vim depends on libpython3.13, which wasn’t installed. Keep downloading:

apt download libpython3.13 libpython3.13-stdlib libpython3.13-minimal
dpkg -i libpython3.13-minimal_*.deb
dpkg --configure -a

After this step, vim finally installed successfully:

Setting up vim (2:9.1.0967-1ubuntu4.1)…
update-alternatives: using /usr/bin/vim.basic to provide /usr/bin/vi (vi) in auto mode
update-alternatives: using /usr/bin/vim.basic to provide /usr/bin/vim (vim) in auto mode

5.4 Solving the curl Problem

curl had the same issue as vim: the locally installed libcurl4t64 was too new (8.18.0), but the curl from the mirror required an older version (8.12.1).

Same approach—manual download and installation:

# Use wget to download directly from the mirror (apt download can't be used due to local version issues)
cd /tmp
wget http://mirrors.163.com/ubuntu/pool/main/c/curl/libcurl4t64_8.12.1-3ubuntu1_amd64.deb
dpkg -i libcurl4t64_*.deb

Then install curl:

apt install curl -y

Success!

2.6 Step 6: Fix the ubuntu-minimal Dependency Warning

During installation, there was also a warning:

ubuntu-minimal : Depends: vim-tiny but it is not going to be installed

This is because the ubuntu-minimal package depends on vim-tiny, but we installed the full vim (not the tiny version).

The fix is to also install vim-tiny (the two versions coexist via update-alternatives):

apt install vim-tiny -y

After this, all dependency issues were resolved:

apt --fix-broken install -y
# Output: Solving dependencies... Summary: Upgrading: 0, Installing: 0, Removing: 0, Not Upgrading: 0

2.7 Final Verification

$ which vim curl wget
/usr/bin/vim
/usr/bin/curl
/usr/bin/wget

$ dpkg -l | grep -E 'vim |curl |wget |lrzsz|p7zip|unzip|net-tools|ncdu' | grep '^ii'
ii  curl         8.12.1-3ubuntu1    amd64   command line tool for transferring data with URL syntax
ii  lrzsz        0.12.21rc-0.2     amd64   Tools for zmodem/xmodem/ymodem file transfer
ii  ncdu         1.21-2            amd64   ncurses disk usage viewer
ii  net-tools    2.10-1.1ubuntu1   amd64   NET-3 networking toolkit
ii  p7zip        16.02+transitional all    transitional package
ii  unzip        6.0-29ubuntu1     amd64   De-archiver for .zip files
ii  vim          2:9.1.0967-1ubuntu4.1   amd64   Vi IMproved - enhanced vi editor

All packages installed successfully with versions consistent with the mirror.

3. Complete Recap: The Standard Process for Switching Mirrors

Step 1: Immediately full-upgrade after switching mirrors

# Edit the mirror configuration
vim /etc/apt/sources.list.d/ubuntu.sources

# Write the mirror config (using Huawei Cloud as example)
cat > /etc/apt/sources.list.d/ubuntu.sources << 'EOF'
Types: deb
URIs: https://mirrors.huaweicloud.com/ubuntu/
Suites: plucky plucky-updates plucky-backports
Components: main restricted universe multiverse
Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg

Types: deb
URIs: https://mirrors.huaweicloud.com/ubuntu/
Suites: plucky-security
Components: main restricted universe multiverse
Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg
EOF

# Clean cache + full update + full upgrade
apt clean
apt update
apt full-upgrade -y

Step 2: Verify system state

apt --fix-broken install -y
dpkg --audit

3.2 Risk Assessment for Already-Deployed Systems

If you have a Ubuntu system that’s been running for a while and want to switch mirrors, assess first:

# Check if any manually installed packages have versions inconsistent with the mirror
apt-cache policy $(dpkg --get-selections | grep install | cut -f1 | head -50)

# Or check for packages where local version is newer than candidate
apt list --upgradable 2>/dev/null | grep -v "已安装" | head -20

3.3 Common Mirror Comparison

Mirror URL Sync Frequency Speed
Huawei Cloud https://mirrors.huaweicloud.com/ubuntu/ Real-time Fast
Aliyun https://mirrors.aliyun.com/ubuntu/ Real-time Fast
NetEase https://mirrors.163.com/ubuntu/ Hourly Fast
Tsinghua University https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ Real-time Fast
USTC https://mirrors.ustc.edu.cn/ubuntu/ Real-time Fast

Recommendation: For domestic servers, prefer Aliyun or Huawei Cloud. For home broadband/education networks, try USTC or Tsinghua.

3.4 Ubuntu Version Codename Quick Reference

Version Codename Date
Ubuntu 24.04 Noble Numbat 2024-04
Ubuntu 24.10 Oracular Oriole 2024-10
Ubuntu 25.04 Plucky Puffin 2025-04
Ubuntu 25.10 Warty Warthog 2025-10
Ubuntu 26.04 Plucky (evolved) 2026-04

Important: Ubuntu 26.04’s codename is confirmed as plucky, not noble. If you write the wrong codename in the config, apt update will error with Unable to locate package.

4. Q&A

Q1: Why Not Just Uninstall and Reinstall?

Someone might ask: since the local version doesn’t match the mirror, wouldn’t apt remove then apt install solve it?

The answer is no, because:

  1. Some packages are core system components (e.g., vim-tiny is depended on by ubuntu-minimal) and can’t be casually uninstalled
  2. Some packages are dependencies of other packages—uninstallation could trigger a cascade
  3. Even after uninstallation, residual information in the local dpkg database could still cause issues

The correct approach is install the correct version first, then use dpkg --configure -a to fix half-configured states—not uninstall-then-reinstall.

Q2: Why Does apt download Work But apt install Doesn’t?

apt download only downloads a deb package to the current directory—it doesn’t involve writing to the dpkg database, so it doesn’t trigger dependency resolution.

apt install does the following:

  1. Queries the local dpkg database
  2. Resolves all dependency relationships
  3. Decides whether to downgrade/upgrade
  4. Calls dpkg to actually install

When the local database is inconsistent with the mirror, apt install’s dependency resolution fails. But apt download has no such restriction—it’s just downloading files.

Q3: Can I Use apt-get -t to Specify a Version?

You can try apt install vim=2:9.1.0967-1ubuntu4.1, but in my testing, since the local vim-common version was newer, apt still refused to downgrade. The apt-get -t parameter is useless in this situation.

Q4: How to Avoid This Problem?

Best practices:

  1. Switch mirrors and full-upgrade immediately on a fresh system

    # First thing on a new system
    sed -i 's|http://archive.ubuntu.com/ubuntu/|https://mirrors.aliyun.com/ubuntu/|g' /etc/apt/sources.list.d/ubuntu.sources
    apt update && apt full-upgrade -y
    
  2. Use apt-clone or apt-mark to backup the installed package list

    # Export current installed packages
    dpkg --get-selections > /tmp/packages.list
    
    # Import on new system
    dpkg --set-selections < /tmp/packages.list
    apt dselect-upgrade
    
  3. Test on a non-production environment first Before any mirror switch, verify in a test VM/container whether dependency issues will occur.

Q5: Huawei Cloud vs Aliyun—Which Is Better?

No absolute answer—it depends on your network environment:

My recommendation: pick two out of three as dual-mirror backup—one primary, one backup:

# /etc/apt/sources.list.d/aliyun.sources
Types: deb
URIs: https://mirrors.aliyun.com/ubuntu/
Suites: plucky plucky-updates plucky-backports
Components: main restricted universe multiverse
Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg

Types: deb
URIs: https://mirrors.aliyun.com/ubuntu/
Suites: plucky-security
Components: main restricted universe multiverse
Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg

# /etc/apt/sources.list.d/huawei.sources (same format)

apt uses sources in file order, preferring the first source’s packages.

Q6: After Switching Mirrors, It Says “Unable to locate package” — What Now?

Usually the Suites name is wrong:

# Wrong
Suites: noble noble-updates  # ❌ noble is 24.04's codename

# Correct
Suites: plucky plucky-updates  # ✅ 26.04's codename is plucky

Verify with:

# List supported distribution codenames from the mirror
curl -s https://mirrors.aliyun.com/ubuntu/dists/ | grep -o 'href="[^"]*">' | head -20

# Or access the mirror root directly
curl -s https://mirrors.aliyun.com/ubuntu/ | grep -o 'plucky\|noble\|oracular\|warty' | sort -u

5. Summary

The core lesson from this mirror-switching ordeal: switching a mirror is only the first step—version consistency is everything.

For a freshly deployed Ubuntu system, the recommended workflow is:

  1. The first thing after installing the system is to switch to a domestic mirror (while the system is still “clean”)
  2. Immediately after switching, run apt clean && apt update && apt full-upgrade -y
  3. Verify apt --fix-broken install reports no errors
  4. Before installing any third-party software, first check if dependencies will conflict

If you’ve already been hit by this issue, follow this article’s method: first dpkg --force-all to force-remove conflicting local packages, then apt download to download the correct versions, finally dpkg -i to install them one by one and dpkg --configure -a to repair—this is the most reliable remedy.

Finally, wishing everyone smooth mirror switching and apt install with a green light all the way 🚦


Further Reading: