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
- Set both owner-uid and owner-gid together (e.g. 1000:1000), or remove both
- 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
- Treat owner-uid and owner-gid as one unit in config templates and Helm values
- Add a config lint that flags one without the other
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
- floci.storage.efs root-permissions must be 3-4 octal digits
- shared-volume init for ${volumeName} exited with status ${st
- No free port available in range ${basePort}-${maxPort}
- Persistent storage path '" + root.toAbsolutePath() + "' is n
- Unknown storage mode: " + mode
AI-assisted analysis of floci-io/floci@62ff490619 (2026-08-14).
Data as JSON: /api/errors/4045ac6155b8e6f4.
Report an issue: GitHub.