{"record":{"id":"4045ac6155b8e6f4","repo":"floci-io/floci","slug":"floci-storage-efs-owner-uid-and-owner-gid-must-be","errorCode":null,"errorMessage":"floci.storage.efs owner-uid and owner-gid must be set together","messagePattern":"floci\\.storage\\.efs owner-uid and owner-gid must be set together","errorType":"console","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"critical","filePath":"src/main/java/io/github/hectorvent/floci/core/common/docker/ContainerLifecycleManager.java","lineNumber":269,"sourceCode":"     * degrades to a plain {@link #ensureVolume}, so the default behaviour is unchanged.\n     *\n     * @param volumeName      the named volume\n     * @param ownerUid        owner uid for the volume root (EFS {@code CreationInfo.OwnerUid})\n     * @param ownerGid        owner gid for the volume root (EFS {@code CreationInfo.OwnerGid})\n     * @param rootPermissions octal permissions for the volume root (e.g. {@code \"0777\"}); empty skips init\n     * @param initImage       lightweight image used for the one-off chown/chmod helper\n     */\n    public void ensureSharedVolume(String volumeName, OptionalInt ownerUid, OptionalInt ownerGid,\n                                   Optional<String> rootPermissions, String initImage) {\n        ensureVolume(volumeName);\n        if (rootPermissions.isEmpty() && ownerUid.isEmpty() && ownerGid.isEmpty()) {\n            return;\n        }\n        // An EFS access point's CreationInfo requires OwnerUid and OwnerGid together; reject a\n        // partial ownership config rather than emitting a malformed `chown uid:` (whose trailing\n        // colon makes chown resolve the login group and fail in busybox for an unknown uid).\n        if (ownerUid.isPresent() != ownerGid.isPresent()) {\n            throw new IllegalArgumentException(\n                    \"floci.storage.efs owner-uid and owner-gid must be set together\");\n        }\n        // Validate before splicing into the helper's `sh -c`, matching CreationInfo.Permissions\n        // (^[0-7]{3,4}$), so a typo can't produce a mangled script that soft-fails.\n        rootPermissions.ifPresent(p -> {\n            if (!p.matches(\"^[0-7]{3,4}$\")) {\n                throw new IllegalArgumentException(\n                        \"floci.storage.efs root-permissions must be 3-4 octal digits (e.g. \\\"0777\\\",\"\n                                + \" or \\\"2775\\\" for setgid): \" + p);\n            }\n        });\n        // computeIfAbsent runs the one-off init under a per-volume lock, so a concurrent launch for\n        // the same volume waits for it to finish rather than mounting a still root:root 0755 root.\n        // Returning null on failure leaves the volume unmemoised, so the next launch retries.\n        initializedSharedVolumes.computeIfAbsent(volumeName, k -> {\n            try {\n                initSharedVolumeRoot(volumeName, ownerUid, ownerGid, rootPermissions, initImage);\n                return Boolean.TRUE;","sourceCodeStart":251,"sourceCodeEnd":287,"githubUrl":"https://github.com/floci-io/floci/blob/62ff490619e7bd3554597c28c704081b4c15add5/src/main/java/io/github/hectorvent/floci/core/common/docker/ContainerLifecycleManager.java#L251-L287","documentation":"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.","triggerScenarios":"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().","commonSituations":"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.","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"],"exampleFix":"# before\nfloci.storage.efs.owner-uid: 1000\n\n# after\nfloci.storage.efs.owner-uid: 1000\nfloci.storage.efs.owner-gid: 1000","handlingStrategy":"validation","validationCode":"boolean ownershipConfigValid(OptionalInt uid, OptionalInt gid) {\n    return uid.isPresent() == gid.isPresent();\n}","typeGuard":null,"tryCatchPattern":"try {\n    manager.ensureSharedVolume(vol, ownerUid, ownerGid, perms, initImage);\n} catch (IllegalArgumentException e) {\n    // config error: fix floci.storage.efs owner-uid/owner-gid, do not retry unchanged\n}","preventionTips":["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"],"tags":["docker","efs","config","shared-volume","startup"],"backgroundTag":null,"analyzedSha":"62ff490619e7bd3554597c28c704081b4c15add5","analyzedAt":"2026-08-14T14:25:23.764Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}