floci-io/floci · critical · IllegalArgumentException

floci.storage.efs owner-uid and owner-gid must be set togeth

Error message

floci.storage.efs owner-uid and owner-gid must be set together

What it means

Thrown by ContainerLifecycleManager.ensureSharedVolume when exactly one of owner-uid / owner-gid is configured for an EFS-backed shared volume (floci.storage.efs). EFS access-point CreationInfo requires OwnerUid and OwnerGid together, and emitting a partial 'chown uid:' would make busybox chown resolve a login group and fail. Deliberate fail-fast validation before any container is launched.

Source

Thrown at src/main/java/io/github/hectorvent/floci/core/common/docker/ContainerLifecycleManager.java:269

     * degrades to a plain {@link #ensureVolume}, so the default behaviour is unchanged.
     *
     * @param volumeName      the named volume
     * @param ownerUid        owner uid for the volume root (EFS {@code CreationInfo.OwnerUid})
     * @param ownerGid        owner gid for the volume root (EFS {@code CreationInfo.OwnerGid})
     * @param rootPermissions octal permissions for the volume root (e.g. {@code "0777"}); empty skips init
     * @param initImage       lightweight image used for the one-off chown/chmod helper
     */
    public void ensureSharedVolume(String volumeName, OptionalInt ownerUid, OptionalInt ownerGid,
                                   Optional<String> rootPermissions, String initImage) {
        ensureVolume(volumeName);
        if (rootPermissions.isEmpty() && ownerUid.isEmpty() && ownerGid.isEmpty()) {
            return;
        }
        // An EFS access point's CreationInfo requires OwnerUid and OwnerGid together; reject a
        // partial ownership config rather than emitting a malformed `chown uid:` (whose trailing
        // colon makes chown resolve the login group and fail in busybox for an unknown uid).
        if (ownerUid.isPresent() != ownerGid.isPresent()) {
            throw new IllegalArgumentException(
                    "floci.storage.efs owner-uid and owner-gid must be set together");
        }
        // Validate before splicing into the helper's `sh -c`, matching CreationInfo.Permissions
        // (^[0-7]{3,4}$), so a typo can't produce a mangled script that soft-fails.
        rootPermissions.ifPresent(p -> {
            if (!p.matches("^[0-7]{3,4}$")) {
                throw new IllegalArgumentException(
                        "floci.storage.efs root-permissions must be 3-4 octal digits (e.g. \"0777\","
                                + " or \"2775\" for setgid): " + p);
            }
        });
        // computeIfAbsent runs the one-off init under a per-volume lock, so a concurrent launch for
        // the same volume waits for it to finish rather than mounting a still root:root 0755 root.
        // Returning null on failure leaves the volume unmemoised, so the next launch retries.
        initializedSharedVolumes.computeIfAbsent(volumeName, k -> {
            try {
                initSharedVolumeRoot(volumeName, ownerUid, ownerGid, rootPermissions, initImage);
                return Boolean.TRUE;

View on GitHub (pinned to 62ff490619)

Solutions

  1. Set both owner-uid and owner-gid together (e.g. 1000:1000), or remove both
  2. After fixing, restart floci so the volume init runs again — the check happens before the one-off chown helper container

Example fix

# before
floci.storage.efs.owner-uid: 1000

# after
floci.storage.efs.owner-uid: 1000
floci.storage.efs.owner-gid: 1000
Defensive patterns

Strategy: validation

Validate before calling

boolean ownershipConfigValid(OptionalInt uid, OptionalInt gid) {
    return uid.isPresent() == gid.isPresent();
}

Try / catch

try {
    manager.ensureSharedVolume(vol, ownerUid, ownerGid, perms, initImage);
} catch (IllegalArgumentException e) {
    // config error: fix floci.storage.efs owner-uid/owner-gid, do not retry unchanged
}

Prevention

When it happens

Trigger: Setting FLOCI_STORAGE_EFS_OWNER_UID (or floci.storage.efs.owner-uid) without owner-gid, or vice versa, in application.yml / environment while EFS shared storage is enabled. Comparison is ownerUid.isPresent() != ownerGid.isPresent().

Common situations: Copying a partial example config; adding owner-uid to run a container as non-root but forgetting the group; upgrading floci versions where the ownership config keys were introduced.

Related errors


AI-assisted analysis of floci-io/floci@62ff490619 (2026-08-14). Data as JSON: /api/errors/4045ac6155b8e6f4. Report an issue: GitHub.