Skip to content

fix(engine): start-plan names crun unconditionally, so a venue without that handler cannot start #16

Open

Description

@aitrawog

Finding

The engine: containerd start-plan fills an empty runtime handler with crun
unconditionally, so on a venue whose containerd has no crun handler the unit
can never start. Measured on this host's rootless containerd 2.3.5 while
proving opencharly/charly#1109:

$ command -v crun
$
$ nerdctl --address /run/containerd/containerd.sock --namespace default run --rm --entrypoint /bin/true quay.io/fedora/fedora:43
rc=0
$ nerdctl ... run --rm --runtime runc --entrypoint /bin/true quay.io/fedora/fedora:43
rc=0
$ nerdctl ... run --rm --runtime io.containerd.runc.v2 --entrypoint /bin/true quay.io/fedora/fedora:43
rc=0
$ nerdctl ... run --rm --runtime crun --entrypoint /bin/true quay.io/fedora/fedora:43
level=fatal msg="failed to start shim: failed to resolve runtime path: invalid runtime name crun, correct runtime name should be either format like `io.containerd.runc.v2` or a full path to the binary"

The generated systemd unit's ExecStart carries --runtime crun; the unit
fails, systemd restart-loops, and the container is left in Created with its
name taken, so every retry fails name-store error: name ... already used.

RCA

  • Mechanism. The containerd provider's start_plan policy names a runtime
    handler always (the capability row's runtime_handlers includes crun) and
    fills an empty request with crun. That validates the WORD against the
    CAPABILITY ROW, not against the VENUE's actually-registered handlers.
  • Missed control. No probe of the venue's containerd runtimes (crictl info / the containerd config) before naming the handler, and no fallback to
    the venue's default (runc / io.containerd.runc.v2) when the named handler
    is absent. The plugin-containerd check verb's runtimes method exists for
    exactly this observation but the start-plan does not consult it.
  • Blast radius. Every containerd venue without a registered crun (this
    desktop host; a stock containerd install): the pod deploy's unit restart-loops
    and cannot start, and the failed attempt leaves a container name residue.
  • Suggested fix. Select the runtime from the VENUE's declared handlers
    (probe the daemon; keep the capability row as the candidate set), fall back to
    the venue default when the named handler is absent, or expose a deploy-level
    runtime: selector. Also clean up the partially-created container on start
    failure so the retry is not blocked by the name store.

Agent: containerd-crabbox-program/engine
Assisted-by: Claude Code ollama-cloud/deepseek-v4.1-flash:cloud (analysed on a live system)

Activity

  1. aitrawog commented on Nov 5, 2026

    @aitrawog
    ContributorAuthor

    STATUS — the venue-facing half of this issue is fixed in opencharly/plugin-deploy-pod#49 (branch fix/venue-runtime-handler, head 038d0323b553c3568a342966c162740ba2ae33c0).

    • charly config / charly start now probe the venue (exec.LookPath over the runtime executable — the SAME resolution nerdctl applies to a bare --runtime word) and REFUSE when the selected handler is absent, naming the handler charly selected, the handlers the venue reports, and the remedy. No fallback to another runtime handler.
    • A failed start now stops the unit (so Restart=always cannot re-create the container) and removes the partial container through the engine teardown argv, so a retry is not blocked by name ... already used.
    • Measured on this host (rootless containerd 2.3.5, nerdctl 2.4.1): nerdctl info carries no Runtimes map in either mode; --runtime crun fails failed to resolve runtime path: invalid runtime name crun; --runtime runc succeeds.

    Still open on the engine side: candy/plugin-containerd/plugin.go's own defaultRuntimeHandler = "crun" is the same unconditional default; it is not on the pod consumer path and is not changed by #49. The repo's R10 bed could not complete on this host (its pinned image is anonymously denied by ghcr.io; filed as opencharly/plugin-deploy-pod#48, reproduced on unmodified origin/main).

    Agent: containerd-crabbox-program/rt16 · session 8b1c01cf-7f79-4a75-bff8-240415a06208
    Assisted-by: Claude Code deepseek-v4.1-flash:cloud (analysed on a live system)

  2. aitrawog commented on Nov 5, 2026

    @aitrawog
    ContributorAuthor

    STATUS — the venue-facing half landed: opencharly/plugin-deploy-pod#49 was validated PASS and merged as 6e9e883331cad4ce0ccff315e8a2796323c38491, tagged v2026.309.2122 (CHANGELOG commit 64bb211).

    What shipped: charly config / charly start probe the venue (exec.LookPath over the runtime executable — the same resolution nerdctl applies to a bare --runtime word) and REFUSE when the selected handler is absent, naming the selected handler, the handlers the venue reports and the remedy; a failed start stops the unit and removes the partial container through the engine teardown argv, so a retry is no longer blocked by name ... already used. No fallback to another runtime handler.

    Still open here: candy/plugin-containerd/plugin.go's own defaultRuntimeHandler = "crun" is the same unconditional default, not on the pod consumer path, and was deliberately not touched by #49.

    Agent: containerd-crabbox-program/rt16 · session 8b1c01cf-7f79-4a75-bff8-240415a06208
    Assisted-by: Claude Code deepseek-v4.1-flash:cloud (analysed on a live system)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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