cross-rs/cross · warning

container was exited.

Error message

container {container_id} was exited.

What it means

Continuing the same startup cleanup, if the leftover remote-build container exists but is stopped (exited), cross warns that it was exited and removes it before proceeding so the new run can create a fresh container with the same ID.

Solutions

  1. Nothing required — cross removes the exited container automatically.
  2. If it recurs often, check why prior runs exit abnormally (build errors, OOM, CI cancellation) and fix the root cause.
  3. Manually prune with `docker container prune` if stale containers accumulate.

Example fix

# before: stale exited container
 docker ps -a # shows exited cross container

# after
docker container prune
cross build --remote --target aarch64-unknown-linux-gnu
Defensive patterns

Strategy: fallback

Validate before calling

# Detect stale exited containers before a remote run
id=$(docker ps -aq --filter name=cross- --filter status=exited)
[ -n "$id" ] && docker rm "$id"

Prevention

When it happens

Trigger: run() inspects the leftover container, state.exists() is true and it is stopped (not running), so the `was exited` warning fires and the container is removed.

Common situations: A previous cross remote build ended abnormally leaving an exited container; a build error stopped the container but cross never cleaned it up; CI cancellations.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of cross-rs/cross@8c1a8aa4b6 (2026-09-13). Data as JSON: /api/errors/f6ab39cfae90c69e. Report an issue: GitHub.

Appendix: source

Thrown at src/docker/remote.rs:808

            let partial = format!("{VOLUME_PREFIX}{}", toolchain_dirs.toolchain());
            if existing.iter().any(|v| v.starts_with(&partial)) {
                msg_info.warn(format_args!(
                    "a persistent volume does not exists for `{0}`, but there is a volume for a different version.\n > Create a new volume with `cross-util volumes create --toolchain {0}`",
                    toolchain_dirs.toolchain()
                ))?;
            }
            VolumeId::Discard
        }
    };

    let container = DockerContainer::new(engine, &container_id);
    let state = container.state(msg_info)?;
    if !state.is_stopped() {
        msg_info.warn(format_args!("container {container_id} was running."))?;
        container.stop_default(msg_info)?;
    }
    if state.exists() {
        msg_info.warn(format_args!("container {container_id} was exited."))?;
        container.remove(msg_info)?;
    }

    // 2. create our volume to copy all our data over to
    // we actually use an anonymous volume, so it's auto-cleaned up,
    // if we're using a discarded volume.

    // 3. create our start container command here
    let mut docker = engine.subcommand("run");
    docker.add_userns();
    options
        .image
        .platform
        .specify_platform(&options.engine, &mut docker);
    docker.args(["--name", &container_id]);
    docker.arg("--rm");
    docker.args(["-v", &volume.mount(mount_prefix)]);

View on GitHub (pinned to 8c1a8aa4b6)