Skip to content

flat-manager in container panics with Failed to read config file though file is readable and JSON-valid #156

@j-urobles

Description

@j-urobles

TL;DR: Running ghcr.io/flatpak/flat-manager:latest under Podman consistently crashes with thread 'main' panicked … Failed to read config file even though the file is mounted, world-readable, free of BOM/CRLF, and its JSON validates against the example schema. The same happens when setting REPO_CONFIG, changing mount paths (/etc/flat-manager, /etc/config.json, /srv/flatman/config.json), fixing HOME/WorkingDir, and switching between relative/absolute repo paths.


Environment

  • Host OS: openSUSE Leap Micro (transactional system)

  • Container runtime: Podman (rootless user session units via systemd/quadlet)

  • Image: ghcr.io/flatpak/flat-manager:latest

    • Image ID / digest: 20d8120765e571adc31c0c19f11118b8d714cdef83e310005b5d004640ac38d0
  • Networking: user bridge flatnet (Podman)

  • Database: Postgres 16 in a sibling container on the same network (connectivity is fine; the crash happens before DB usage)

If helpful, I can add the outputs of podman --version and uname -a.


Reproducer (minimal)

1) Prepare data dirs (host):

mkdir -p /home/jurobles/flatmanager/{config,data}

2) Initialize repos inside the image (host):

podman run --rm \
  -v /home/jurobles/flatmanager/data:/var/lib/flat-manager:Z \
  ghcr.io/flatpak/flat-manager:latest \
  sh -lc 'ostree --repo=/var/lib/flat-manager/repo init --mode=archive-z2 && \
          mkdir -p /var/lib/flat-manager/build-repo'

3) Config file (host): /home/jurobles/flatmanager/config/config.json

(sanitized; password redacted)

{
  "repos": {
    "stable": {
      "path": "repo",
      "collection-id": "com.paco.Stable",
      "suggested-repo-name": "paco",
      "runtime-repo-url": "https://dl.flathub.org/repo/flathub.flatpakrepo",
      "gpg-key": null
    }
  },
  "port": 8080,
  "delay-update-secs": 10,
  "database-url": "postgres://flatmanager:<REDACTED>@db:5432/repo",
  "build-repo-base": "build-repo",
  "build-gpg-key": null,
  "gpg-homedir": null,
  "secret": "c2VjcmV0"
}

4) Run flat-manager (variant A: config under /etc/flat-manager)

podman run --rm --network flatnet \
  -e HOME=/var/lib/flat-manager \
  -e REPO_CONFIG=/etc/flat-manager/config.json \
  -e RUST_LOG=trace \
  -e RUST_BACKTRACE=full \
  -v /home/jurobles/flatmanager/config/config.json:/etc/flat-manager/config.json:ro,Z \
  -v /home/jurobles/flatmanager/data:/var/lib/flat-manager:Z \
  ghcr.io/flatpak/flat-manager:latest

Observed output:

[2025-08-20T09:52:26Z TRACE mio::poll] registering with poller

thread 'main' panicked at src/lib.rs:39:51:
Failed to read config file "/etc/flat-manager/config.json"
stack backtrace:
   0:     0x55f534ae0bd2 - <std::sys::backtrace::BacktraceLock::print::DisplayBacktrace as core::fmt::Display>::fmt::h46a716bba2450163
   1:     0x55f534b0ac53 - core::fmt::write::h275e5980d7008551
   2:     0x55f534add213 - std::io::Write::write_fmt::h561a66a0340b6995
   3:     0x55f534ae0a22 - std::sys::backtrace::BacktraceLock::print::hafb9d5969adc39a0
   4:     0x55f534ae2a92 - std::panicking::default_hook::{{closure}}::hae2e97a5c4b2b777
   5:     0x55f534ae2895 - std::panicking::default_hook::h3db1b505cfc4eb79
   6:     0x55f534ae3432 - std::panicking::rust_panic_with_hook::h409da73ddef13937
   7:     0x55f534ae31da - std::panicking::begin_panic_handler::{{closure}}::h159b61b27f96a9c2
   8:     0x55f534ae10c9 - std::sys::backtrace::__rust_end_short_backtrace::h5b56844d75e766fc
   9:     0x55f534ae2e6d - __rustc[4794b31dd7191200]::rust_begin_unwind
  10:     0x55f534598f70 - core::panicking::panic_fmt::hc8737e8cca20a7c8
  11:     0x55f534577319 - flatmanager::load_config::{{closure}}::hecc72c2099acbb07
  12:     0x55f5345bbabb - flatmanager::load_config::haaa4977d39fbeb7e
  13:     0x55f5345a232e - tokio::runtime::park::CachedParkThread::block_on::he8979704017212ed
  14:     0x55f53459d663 - tokio::runtime::context::runtime::enter_runtime::h7c8f17bc67ecd01b
  15:     0x55f5345a104e - tokio::runtime::runtime::Runtime::block_on::h29fb04bdfc26debb
  16:     0x55f53459f460 - flat_manager::main::h720cc119c919633a
  17:     0x55f53459db23 - std::sys::backtrace::__rust_begin_short_backtrace::h7767311fb6a229cd
  18:     0x55f5345a0589 - std::rt::lang_start::{{closure}}::h77d33693c2aab7e2
  19:     0x55f534ad3b04 - std::rt::lang_start_internal::ha8ef919ae4984948
  20:     0x55f53459f515 - main
  21:     0x7f179572bd90 - <unknown>
  22:     0x7f179572be40 - __libc_start_main
  23:     0x55f534599765 - _start
  24:                0x0 - <unknown>

5) Sanity check: the file is there and readable inside the container

podman run --rm --network flatnet \
  -v /home/jurobles/flatmanager/config/config.json:/etc/flat-manager/config.json:ro,Z \
  -v /home/jurobles/flatmanager/data:/var/lib/flat-manager:Z \
  -w /var/lib/flat-manager \
  -e REPO_CONFIG=/etc/flat-manager/config.json \
  ghcr.io/flatpak/flat-manager:latest \
  sh -lc 'cat /etc/flat-manager/config.json'

Output (inside the container):

{
  "repos": {
    "stable": {
      "path": "repo",
      "collection-id": "com.paco.Stable",
      "suggested-repo-name": "paco",
      "runtime-repo-url": "https://dl.flathub.org/repo/flathub.flatpakrepo",
      "gpg-key": null
    }
  },
  "port": 8080,
  "delay-update-secs": 10,
  "database-url": "postgres://flatmanager:<REDACTED>@db:5432/repo",
  "build-repo-base": "build-repo",
  "build-gpg-key": null,
  "gpg-homedir": null,
  "secret": "c2VjcmV0"
}

Also verified (separate check):

podman run --rm \
  -v /home/jurobles/flatmanager/config/config.json:/srv/flatman/config.json:ro,Z \
  ghcr.io/flatpak/flat-manager:latest \
  sh -lc 'id; ls -ld /srv /srv/flatman /srv/flatman/config.json; \
          stat -c "%U %G %a %n" /srv/flatman/config.json; \
          head -c 1 /srv/flatman/config.json >/dev/null && echo "READ OK"'

Output:

uid=0(root) gid=0(root) groups=0(root)
 drwxr-xr-x. 1 root root  14 Aug 20 09:30 /srv
 drwxr-xr-x. 1 root root  22 Aug 20 09:30 /srv/flatman
 -rw-r--r--. 1 root root 469 Aug 20 09:21 /srv/flatman/config.json
 root root 644 /srv/flatman/config.json
 READ OK

Other variants tested (all with the same panic)

  • Mounting the config at /etc/config.json and exporting REPO_CONFIG=/etc/config.json.
  • Mounting at /srv/flatman/config.json and running flat-manager /srv/flatman/config.json explicitly.
  • Setting HOME=/var/lib/flat-manager and/or WorkingDir=/var/lib/flat-manager.
  • Using relative vs absolute paths in the config for repos.*.path and build-repo-base.
  • Verifying JSON with jq -e . (OK), removing potential BOM and CRLF (sed/tr), and re-testing.
  • Running under systemd user services (Podman quadlets) and also with a plain podman run.

In every case, the process panics at startup with the same message from load_config.


Expected behavior

flat-manager should parse the JSON config and start listening on port 8080 (or log a specific schema error if the content is wrong).

Actual behavior

Immediate panic with Failed to read config file although the file exists and is readable from within the same container context.


Questions / requests for guidance

  1. Is there any additional logging flag to dump the exact I/O or parse error from load_config?
  2. Has the config schema changed recently (e.g., keys like repos, build-repo-base, etc.) in a way that isn’t reflected by example-config.json?
  3. Does the container expect the config to be relative to a specific base dir (e.g., $HOME) during parse time, regardless of REPO_CONFIG?
  4. Any known issues with reading config from paths under /etc/flat-manager/ vs /etc/ vs /srv?

Happy to test patches or build a debug image if needed. Thanks!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions