Subject: bug#77716: Corrupted store after Guix deploy

From: Tomas Volf <[email-masked]>
Date: Mon, 21 Apr 2025 20:34:52 +0200

Ludovic Courtès <[email-masked]> writes:

> Hello,
>
> Tomas Volf <[email-masked]> writes:
>
>> The permissions on the very top level directory differ (which one are
>> correct?):
>>
>> Laptop:
>>
>> --8<---------------cut here---------------start------------->8---
>> $ ls -al /gnu/store/ | grep 1bjf1lza4i7fc1jh8qzb1n9xnv3rfi17-wolfsden
>> drwxr-xr-x   1 root          root              16 Jan  1  1970 1bjf1lza4i7fc1jh8qzb1n9xnv3rfi17-wolfsden
>> --8<---------------cut here---------------end--------------->8---
>>
>> Remote:
>>
>> --8<---------------cut here---------------start------------->8---
>> $ ls -al /gnu/store/ | grep 1bjf1lza4i7fc1jh8qzb1n9xnv3rfi17-wolfsden
>> dr-xr-xr-x  1 root root           16 Jan  1  1970 1bjf1lza4i7fc1jh8qzb1n9xnv3rfi17-wolfsden
>> --8<---------------cut here---------------end--------------->8---
>>
>>
>>
>> The target of symbolic link in the store item differs.
>>
>> Laptop:
>>
>> --8<---------------cut here---------------start------------->8---
>> $ ls -l /gnu/store/1bjf1lza4i7fc1jh8qzb1n9xnv3rfi17-wolfsden/share/guile/site/
>> total 4
>> lrwxrwxrwx 1 root root 61 Jan  1  1970 3.0 -> /gnu/store/rmwi813mcsg8d5ilzq0rxwqd8dp558r5-wolfsden-989d91d/
>> --8<---------------cut here---------------end--------------->8---
>>
>> Remote:
>>
>> --8<---------------cut here---------------start------------->8---
>> $ ls -l /gnu/store/1bjf1lza4i7fc1jh8qzb1n9xnv3rfi17-wolfsden/share/guile/site/
>> total 4
>> lrwxrwxrwx 1 root root 60 Jan  1  1970 3.0 -> /gnu/store/rmwi813mcsg8d5ilzq0rxwqd8dp558r5-wolfsden-989d91d
>> --8<---------------cut here---------------end--------------->8---
>>
>> Notice that for the Laptop, the target ends in `/', for the Remote it
>> does not.
>
> Interesting.
>
> There are several code paths to add a store item to the store.  One is
> through (guix store …), use by ‘guix offload’.  One is through ‘guix
> substitute’, which restores nars it downloaded.  One is through a build
> via guix-daemon (C++ code).
>
> Could you tell how these two differing things were obtained?
>
> On each machine, run ‘guix build --log-file /gnu/store/1bjf1lza4i7fc1jh8qzb1n9xnv3rfi17-wolfsden’.  If
> there’s a local log file, it was built locally or offloaded; otherwise
> it was substituted.

Definitely, I am pretty sure I know how these were acquired.  It is my
personal Guix channel, and I am not using any substitutes other then the
official ones.  On my local system (the "Laptop" above), I have executed
the following:

--8<---------------cut here---------------start------------->8---
guix pull --no-offload -C wolfsnet/files/channels-base.sex
--8<---------------cut here---------------end--------------->8---

During that, Guix was pulled using this channels file:

--8<---------------cut here---------------start------------->8---
(cons* (channel
        (name 'guix)
        (url "https://git.wolfsden.cz/.git/guix")
        (introduction
         (make-channel-introduction
          "028e445a2028068e3c83996daa281057f19141a0"
          (openpgp-fingerprint
           "B783 49B3 8C14 7D36 2988  68A4 2FBF EE7D B67F C1A9"))))
       (channel
        (name 'wolfsden)
        (url "https://git.wolfsden.cz/.git/wolfsden")
        (introduction
         (make-channel-introduction
          "49d7c72d2c3ae36ae8cf045dc7c00da29801af2c"
          (openpgp-fingerprint
           "B783 49B3 8C14 7D36 2988  68A4 2FBF EE7D B67F C1A9"))))
       (channel
        (name 'nonguix)
        (url "https://gitlab.com/nonguix/nonguix")
        (introduction
         (make-channel-introduction
          "897c1a470da759236cc11798f4e0a5f7d4d59fbc"
          (openpgp-fingerprint
           "2A39 3FFF 68F4 EF7A 3D29  12AF 6F51 20A0 22FB B2D5"))))
       (filter (negate guix-channel?) %default-channels))
--8<---------------cut here---------------end--------------->8---

Since 'wolfsden has no substitutes on official servers, the store item
was built locally (on "Laptop").  After that, I did `guix deploy' onto
"Remote".  Since I am using the channel in few places in the system
definition, it was copied over to "Remote" as part of the deploy.

Additionally I am using the "current" Guix as the (guix) field of the
guix-configuration, but I am pretty sure that is not relevant here, so I
am including it just for completeness (in case I am wrong).

--8<---------------cut here---------------start------------->8---
(define (%current-guix)
  (let ((guix-bin (car (command-line))))
    (unless (string-suffix? "/bin/guix" guix-bin)
      (error "Does not look like guix binary" guix-bin))
    (let* ((guix-profile (string-drop-right guix-bin 9))
           (guix-profile (canonicalize-path guix-profile)))
      (package
        (name "custom-guix")
        (version "1")
        (source #f)
        (build-system trivial-build-system)
        (arguments
         (list
          #:builder
          #~(symlink #$guix-profile #$output)))
        (home-page #f)
        (synopsis #f)
        (description #f)
        (license #f)))))

[..]

(operating-system
        ...
        (services
          (modify-services %base-services
            (guix-service-type
             config => (guix-configuration
                        (inherit config)
                        (channels %channels)
                        (guix (%current-guix)))))))
--8<---------------cut here---------------end--------------->8---

To sum up, to the "broken" system ("Remote") the store item got via
`guix deploy'.

>
> Could you also report the guix-daemon versions that are running on each
> machine?

Sadly I am not sure how to tell now :/.  My laptop got updated and the
VM got shut down.  I will be sure to gather this information next time.
Maybe it would be useful to include this information in the log files
for the builds.  All I can say now is that guix-daemon on both was
"reasonably recent", definitely under 2 months old, probably under
month.

>
> An interesting puzzle.  :-)

I am glad you have found this interesting. :)

Tomas

-- 
There are only two hard things in Computer Science:
cache invalidation, naming things and off-by-one errors.