Skip to content

[Bug]: Failed startup loads can delete bundles and publish unusable state #2033

Description

@stephenlclarke

I have done the following

  • I have searched the existing issues
  • I have reproduced the issue using the main branch of this project

Steps to reproduce

During testing of my Container Compose plugin, I found two related startup persistence failures on stock apple/container main at 48145ac7fb177d9fb14e015a0bdea4c642b36729.

Unloadable metadata

  1. Create a directory under the container bundle root.
  2. Put malformed JSON in both config.json and the legacy fallback runtime-configuration.json.
  3. Call ContainersService.loadAtBoot.
  4. Observe that the entire bundle directory is deleted by the catch block.

Missing runtime plugin

  1. Create a valid container bundle whose configuration names a runtime plugin that is not currently registered.
  2. Call ContainersService.loadAtBoot.
  3. Observe that a stopped ContainerState is inserted before runtime availability is checked.
  4. The subsequent error is caught and the bundle is deleted, but the unusable in-memory state remains in the returned dictionary.

The same bundle writer persists JSON directly to config.json, options.json, kernel.json, and rootfs.json. A process interruption during one of these writes can therefore leave truncated metadata that triggers the destructive startup path.

Problem description

ContainersService.loadAtBoot deletes a user's complete on-disk container bundle for every load error, including transient runtime-plugin availability and recoverable metadata errors. In the missing-runtime case, it also returns an in-memory state for the bundle it just deleted because state insertion happens before validation.

Startup should preserve unloadable bundles for diagnosis or a later successful load, reject them from the returned in-memory state, and log the failure. Bundle metadata replacements should be atomic so an interrupted write cannot expose partially written JSON.

Environment

  • OS: macOS 26.5.1 (25F80)
  • Xcode: 26.6 (17F113)
  • Swift: 6.3.3
  • Container: source main at 48145ac7fb177d9fb14e015a0bdea4c642b36729

Code of Conduct

  • I agree to follow this project's Code of Conduct

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