Clarification on pkg updating

Hello all,

I have a question regarding how does exactly pkg update work. I.e. what is the logic pkg uses to check whether or not there are updates to execute? I'm asking this because twice recently I've been left with inconsistent packages after an update + upgrade combo. (see below for examples)

In any case, I have to double check every time to see if anything is missing (with pkg version -vRL=) either that or do pkg upgrade -f which does detect the packages in need of upgrade but will reinstall all other packages.

Code:
$ freebsd-version -rku
15.0-STABLE
15.0-STABLE
15.0-STABLE

Code:
$ pkg repositories
FreeBSD-ports: { 
    url             : "pkg+[URL]https://pkg.freebsd.org/FreeBSD:15:amd64/latest[/URL]",
    enabled         : yes,
    priority        : 0,
    mirror_type     : "SRV",
    signature_type  : "FINGERPRINTS",
    fingerprints    : "/usr/share/keys/pkg"
  }
FreeBSD-ports-kmods: { 
    url             : "pkg+[URL]https://pkg.freebsd.org/FreeBSD:15:amd64/kmods_latest[/URL]",
    enabled         : yes,
    priority        : 0,
    mirror_type     : "SRV",
    signature_type  : "FINGERPRINTS",
    fingerprints    : "/usr/share/keys/pkg"
  }
FreeBSD-base: { 
    url             : "pkg+[URL]https://pkg.freebsd.org/FreeBSD:15:amd64/base_weekly[/URL]",
    enabled         : yes,
    priority        : 0,
    mirror_type     : "SRV",
    signature_type  : "FINGERPRINTS",
    fingerprints    : "/usr/share/keys/pkg"
  }

Code:
# pkg update -f
Updating FreeBSD-ports repository catalogue...
Fetching meta.conf: 100%    179 B   0.2kB/s    00:01    
Fetching data.pkg: 100%   10 MiB   5.5MB/s    00:02    
Processing entries: 100%
FreeBSD-ports repository update completed. 36872 packages processed.
Updating FreeBSD-ports-kmods repository catalogue...
Fetching meta.conf: 100%    179 B   0.2kB/s    00:01    
Fetching data.pkg: 100%   31 KiB  31.8kB/s    00:01    
Processing entries: 100%
FreeBSD-ports-kmods repository update completed. 207 packages processed.
Updating FreeBSD-base repository catalogue...
Fetching meta.conf: 100%    179 B   0.2kB/s    00:01    
Fetching data.pkg: 100%   79 KiB  81.2kB/s    00:01    
Processing entries: 100%
FreeBSD-base repository update completed. 499 packages processed.
All repositories are up to date.

Code:
# pkg upgrade
Updating FreeBSD-ports repository catalogue...
FreeBSD-ports repository is up to date.
Updating FreeBSD-ports-kmods repository catalogue...
FreeBSD-ports-kmods repository is up to date.
Updating FreeBSD-base repository catalogue...
FreeBSD-base repository is up to date.
All repositories are up to date.
Checking for upgrades (160 candidates): 100%
Processing candidates (160 candidates): 100%
Checking integrity... done (0 conflicting)
Your packages are up to date.

Code:
$ pkg version -vRL= | grep "needs updating"
gstreamer1-plugins-lame-1.26.7     <   needs updating (remote has 1.26.8)
gstreamer1-plugins-x264-1.26.7     <   needs updating (remote has 1.26.8)
level-zero-1.24.3_1                <   needs updating (remote has 1.26.0)
nano-8.6                           <   needs updating (remote has 8.7)
py311-python-xapp-2.4.2            <   needs updating (remote has 3.0.0)
py311-tinycss2-1.4.0               <   needs updating (remote has 1.5.0)
wine-devel-10.19,1                 <   needs updating (remote has 10.20,1)
Code:
# pkg upgrade -f
Updating FreeBSD-ports repository catalogue...
FreeBSD-ports repository is up to date.
Updating FreeBSD-ports-kmods repository catalogue...
FreeBSD-ports-kmods repository is up to date.
Updating FreeBSD-base repository catalogue...
FreeBSD-base repository is up to date.
All repositories are up to date.
Checking for upgrades (1543 candidates): .......... done
Processing candidates (1543 candidates): .......... done
The following 1541 package(s) will be affected (of 0 checked):

Installed packages to be UPGRADED:
        gstreamer1-plugins-lame: 1.26.7 -> 1.26.8 [FreeBSD-ports]
        gstreamer1-plugins-x264: 1.26.7 -> 1.26.8 [FreeBSD-ports]
        level-zero: 1.24.3_1 -> 1.26.0 [FreeBSD-ports]
        nano: 8.6 -> 8.7 [FreeBSD-ports]
        py311-python-xapp: 2.4.2 -> 3.0.0 [FreeBSD-ports]
        py311-tinycss2: 1.4.0 -> 1.5.0 [FreeBSD-ports]
        wine-devel: 10.19,1 -> 10.20,1 [FreeBSD-ports]

Installed packages to be REINSTALLED:
[...]
Number of packages to be upgraded: 7
Number of packages to be reinstalled: 1534

The process will require 2 MiB more space.
4 GiB to be downloaded.

Proceed with this action? [y/N]:
 
My opinions, based just on my experience. I'm sure pkg masters will point out holes.
One could probably look into the code to be completely sure, but you mention "pkg upgrade -f" which is "force upgrade everything".
When you do a system update, especially across releases, you may wind up with pkgs installed on say 14.x that do not exist on 15.x; that's just the way repos work sometimes.
In general pkg upgrade winds up with 3 lists:
pkgs to be upgraded say installed is ver a.b.c, repo has x.y.z
pkgs to be deleted because installed pkg A is ver a.b.c and repo does not have pkg A (perhaps failed to build)
pkgs to be reinstalled because installed pkg B depends on pkg A installed at ver a.b.c, but pkg A will be upgraded to x.y.z That causes pkg B to be reinstalled to link to new ver x.y.z of pkg A. Typically you see "direct dependency changed"

pkg update basically looks at the versions in the remote repos and updates local metadata so subsequent pkg commands look at the local db. apt update on Ubuntu does the same thing.

Sometimes if you look at repos and they are in transition (getting updated) you may wind up with incomplete/mixed up meta data. Normally doesn't happen, but it can.
Most problems I've seen are related to system updates across release (14.x to 15.x) you need to be on 15.x before running pkg update -f (force your local meta data to update to 15.x) then running pkg upgrade -f to forcibly pull in the 15.x versions.
Then you need to look at output of pkg autoremove to maybe clean up any 14.x pkgs in your 15.x system.
 
pkgs to be deleted because installed pkg A is ver a.b.c and repo does not have pkg A (perhaps failed to build)
Installed packages aren't deleted if they disappear in the repository (for whatever reason). They will show up as 'orphaned' if you look at a pkg version -vR. They will remain installed, but obviously cannot be updated. They may only get removed if one of its dependencies got updated.

What can happen, is A getting updated, and B (depending on A) also gets updated, but C (which also depends on A) should be updated too. Unfortunately C failed to build (thus no available package). In that case, C ends up being deleted because it was linked to the previous version of A. In order to preserve the dependency chain it cannot leave C installed. This sometimes results in a cascading effect, because everything that depends on C also gets deleted.

Code:
pkg version -vRL= | grep "needs updating"
Don't grep. If you really only want to know what "needs updating"; pkg version -vRl<
Code:
     -l limchar, --like limchar
                 Display only the packages which status flag matches the one
                 specified by limchar.

     -L limchar, --not-like limchar
                 Does the opposite of -l flag.  Displays the packages which
                 status flag does not match the one specified by limchar.
pkg-version(8)

Stick to pkg version -vRL=. You want to see everything that's not up to date (and thus needs updating), but you should also pay real close attention to the ? (orphaned) packages. So don't grep the output. Find out why a package is orphaned. There might be a good reason for it (port got deprecated for example). But it could also have had build issues, in which case a pkg upgrade might remove things you didn't want to have deleted.

And yes, pkg upgrade -f reinstalls everything, regardless if it needs updating or not. Useful in some situations, but generally not what you want to do.
Code:
     -f, --force
                 Force the reinstallation or upgrade of the whole set of
                 packages.
pkg-upgrade(8)
 
mer and SirDice thank you for the replies.
During the 15 alphas I got some cascade deletes as you mentioned, was not fun.
And yes I have orphaned and succeds packages, I've ommited them to focus on my question.

I'll try and look at the source to see if I can figure out why pkg upgrade reports no updates available when there are.

Ps: thank you for moving the post
 
SirDice you were correct, the solver appears to be conservative in terms of upgrades:

DBG(4)[59483]> (jobs) add new uid py311-tinycss2 to the request
DBG(4)[59483]> (universe) Processing item py311-tinycss2
DBG(4)[59483]> (universe) Processing deps for py311-tinycss2
DBG(4)[59483]> (universe) Processing *deps for py311-tinycss2: python311
DBG(3)[59483]> (package) add a new reverse dependency origin: textproc/py-tinycss2, name: py311-tinycss2
DBG(3)[59483]> (package) add a new reverse dependency origin: textproc/py-tinycss2, name: py311-tinycss2
DBG(4)[59483]> (universe) Processing *deps for py311-webencodings: py311-tinycss2
DBG(4)[59483]> (universe) Processing *deps for python311: py311-tinycss2
DBG(4)[59483]> (universe) Processing *deps for python311: py311-tinycss2
DBG(4)[59483]> (universe) Processing *deps for py311-tinycss2: py311-webencodings
DBG(4)[59483]> (universe) Processing rdeps for py311-tinycss2 (remote)
DBG(4)[59483]> (universe) Processing rdeps for py311-tinycss2 (installed)
DBG(4)[59483]> (solver) add variable from universe with uid py311-tinycss2
DBG(2)[59483]> (solver) rule: dependency rule: package py311-tinycss2(r) depends on: py311-webencodings(l)
DBG(2)[59483]> (solver) rule: dependency rule: package py311-tinycss2(r) depends on: python311(l)python311(r)
DBG(2)[59483]> (solver) rule: upgrade rule: upgrade local py311-tinycss2-1.5.0 to remote py311-tinycss2-1.5.1
DBG(2)[59483]> (solver) rule: dependency rule: package py311-tinycss2(l) depends on: py311-webencodings(l)
DBG(2)[59483]> (solver) rule: dependency rule: package py311-tinycss2(l) depends on: python311(l)python311(r)
DBG(4)[59483]> (solver) not interested in dependencies for py311-tinycss2-1.5.1
DBG(4)[59483]> (solver) not interested in dependencies for py311-tinycss2-1.5.1
DBG(4)[59483]> (solver) not interested in dependencies for py311-tinycss2-1.5.0
DBG(4)[59483]> (solver) not interested in dependencies for py311-tinycss2-1.5.0
DBG(2)[59483]> (solver) decided local py311-tinycss2-2$2$xdxacrjc8b8yhzm3rcumqohhr4g439ukfrsq7mataksyq5f9rbrjfmd183esambn4y68414ym76jz551yoowz3gzx59ox573j4zmthy to install
DBG(2)[59483]> (solver) decided remote py311-tinycss2-2$2$qzy17ntgec9zfj15mb8og7j746z7arbzye8odkbd1a7oun81ymcd7ihnkq9cw77p6du1rhakz4m59dx3nfrzzt61t5tmqmmmifi1hcn to delete
DBG(4)[59483]> (solver) check variable with uid py311-tinycss2
DBG(2)[59483]> (solver) ignoring package py311-tinycss2(2$2$xdxacrjc8b8yhzm3rcumqohhr4g439ukfrsq7mataksyq5f9rbrjfmd183esambn4y68414ym76jz551yoowz3gzx59ox573j4zmthy) as its state has not been changed
For this case it has ignored the updated remote version (1.5.1) because there is no one that depends on that version.
I think this behaviour may lead to issues under some circumstances (other than the cascade delete) if package dependencies are not fully correct/up to date. I'll keep watch and if necessary open a ticket. Thanks for the explanations.
 
By the way SirDice, I was using grep because of the below.
Code:
$ pkg version -vRl<
Syntax error: end of file unexpected (expecting word)
The correct syntax for your particular command is slightly different, for example:
Code:
[1-0] # pkg version -r FreeBSD-base -vRl '<'
Updating FreeBSD-base repository catalogue...
FreeBSD-base repository is up to date.
FreeBSD-base is up to date.
[2-0] #

On the topic of pkg-upgrade(8). It could be that users associate the use of pkg upgrade -f ... with an upgrade*, while it is still, in fact, a forced reinstall. Note that in the context of a major version upgrade of FreeBSD, the base “install” does undergo an actual upgrade. Here it is important to realise that the base system and packages from the ports tree follow different update and release schedules, and of different types. Latest packages are on a rolling-release schedule, whereas quarterly packages follow a quarterly update cycle, as the name implies. The relevant quarterly branch of the ports tree, from which the quarterly packages are built, is labelled with the current year and quarter—for example, 2025Q4. The base system has its own update, release, and support cycles, independent of the ports tree.

Opposite to the notion of an upgrade, with respect to packages from the ports tree, is the concept of a downgrade. This can occur in practice. If one decides to switch from latest to quarterly packages, it is good practice to use pkg upgrade -f .... This is recommended because each package does not stand on its own: there is often a dependency relationship between various packages. Of course, this is still a forced reinstall, but with respect to the version number of a package, it may constitute a downgrade.

___
* What might be the case for an individual user—such as in message #2—I cannot guess, as I have no knowledge of mer 's inner thoughts ;)
 
I have also noticed similar behavior on a computer with:
Code:
# freebsd-version -kru
14.3-RELEASE-p7
14.3-RELEASE-p7
14.3-RELEASE-p7
Today I performed a pkgs update:
Code:
# pkg update
Updating FreeBSD repository catalogue...
FreeBSD repository is up to date.
Updating FreeBSD-kmods repository catalogue...
FreeBSD-kmods repository is up to date.
All repositories are up to date.

# pkg upgrade
Updating FreeBSD repository catalogue...
FreeBSD repository is up to date.
Updating FreeBSD-kmods repository catalogue...
FreeBSD-kmods repository is up to date.
All repositories are up to date.
Checking for upgrades (809 candidates): 100%
Processing candidates (809 candidates): 100%
Checking integrity... done (0 conflicting)
Your packages are up to date.
When running pkg audit, I noticed a package that had long been updated on another PC running FreeBSD 13.5, namely:
Code:
# pkg audit -F
Fetching vuln.xml.xz: 100%    1 MiB 600.0kB/s    00:02
...
xorg-server-21.1.18_1,1 is vulnerable:
  Xorg -- multiple vulnerabilities
  CVE: CVE-2025-62231
  CVE: CVE-2025-62230
  CVE: CVE-2025-62229
  WWW: https://vuxml.FreeBSD.org/freebsd/e99a32c8-b8e2-11f0-8510-b42e991fc52e.html
...
Interestingly, pkg search sees a new version:
Code:
# pkg search xorg-server
xorg-server-21.1.20,1          X.Org X server and related programs

# pkg version -vRL= | grep "needs updating"
xorg-server-21.1.18_1,1            <   needs updating (remote has 21.1.20,1)
But:
Code:
# pkg update
Updating FreeBSD repository catalogue...
FreeBSD repository is up to date.
Updating FreeBSD-kmods repository catalogue...
FreeBSD-kmods repository is up to date.
All repositories are up to date.
# pkg upgrade
Updating FreeBSD repository catalogue...
FreeBSD repository is up to date.
Updating FreeBSD-kmods repository catalogue...
FreeBSD-kmods repository is up to date.
All repositories are up to date.
Checking for upgrades (809 candidates): 100%
Processing candidates (809 candidates): 100%
Checking integrity... done (0 conflicting)
Your packages are up to date.
I just gave up and did it:
Code:
# pkg fetch xorg-server
Updating FreeBSD repository catalogue...
FreeBSD repository is up to date.
Updating FreeBSD-kmods repository catalogue...
FreeBSD-kmods repository is up to date.
All repositories are up to date.
The following packages will be fetched:

New packages to be FETCHED:
        xorg-server: 21.1.20,1 (2 MiB: 100.00% of the 2 MiB to download)

Number of packages to be fetched: 1

The process will require 2 MiB more space.
2 MiB to be downloaded.

Proceed with fetching packages? [y/N]: y
Fetching xorg-server-21.1.20,1~a53cd2d41e.pkg:  14%  239 KiB 245.2kB/s    00:05 
Fetching xorg-server-21.1.20,1~a53cd2d41e.pkg:  62%    1 MiB 786.4kB/s    00:01 
Fetching xorg-server-21.1.20,1~a53cd2d41e.pkg: 100%    2 MiB 825.6kB/s    00:02  

 # pkg upgrade xorg-server
Updating FreeBSD repository catalogue...
FreeBSD repository is up to date.
Updating FreeBSD-kmods repository catalogue...
FreeBSD-kmods repository is up to date.
All repositories are up to date.
Checking integrity... done (0 conflicting)
The following 1 package(s) will be affected (of 0 checked):

Installed packages to be UPGRADED:
        xorg-server: 21.1.18_1,1 -> 21.1.20,1 [FreeBSD]

Number of packages to be upgraded: 1

Proceed with this action? [y/N]: y
[1/1] Upgrading xorg-server from 21.1.18_1,1 to 21.1.20,1...
[1/1] Extracting xorg-server-21.1.20,1: 100%
It seems that running pkg update and pkg upgrade will require more attention...
 
Sorry, I wasn't paying attention.
Code:
# pkg version -vRl '<'
Updating FreeBSD repository catalogue...
FreeBSD repository is up to date.
Updating FreeBSD-kmods repository catalogue...
FreeBSD-kmods repository is up to date.
All repositories are up to date.
 
Back
Top