jenkinsci/jenkins · error · IOException
Invalid mode: {}
Error message
Invalid mode: {} What it means
Thrown by Util.modeToPermissions(int mode) when the mode value, after masking with 07777 (stripping file-type bits), still contains bits in the 07000 range — i.e., setuid (04000), setgid (02000), or sticky (01000). The check is (mode & 0777) != mode after masking; if any bit above 0777 remains, the mode is rejected because these special permission bits are not supported by the POSIX file permission mapping.
Source
Thrown at core/src/main/java/hudson/Util.java:1779
public static int permissionsToMode(Set<PosixFilePermission> permissions) {
PosixFilePermission[] allPermissions = PosixFilePermission.values();
int result = 0;
for (PosixFilePermission allPermission : allPermissions) {
result <<= 1;
result |= permissions.contains(allPermission) ? 1 : 0;
}
return result;
}
@Restricted(NoExternalUse.class)
public static Set<PosixFilePermission> modeToPermissions(int mode) throws IOException {
// Anything larger is a file type, not a permission.
int PERMISSIONS_MASK = 07777;
// setgid/setuid/sticky are not supported.
int MAX_SUPPORTED_MODE = 0777;
mode = mode & PERMISSIONS_MASK;
if ((mode & MAX_SUPPORTED_MODE) != mode) {
throw new IOException("Invalid mode: " + mode);
}
PosixFilePermission[] allPermissions = PosixFilePermission.values();
Set<PosixFilePermission> result = EnumSet.noneOf(PosixFilePermission.class);
for (int i = 0; i < allPermissions.length; i++) {
if ((mode & 1) == 1) {
result.add(allPermissions[allPermissions.length - i - 1]);
}
mode >>= 1;
}
return result;
}
/**
* Converts a {@link File} into a {@link Path} and checks runtime exceptions.
* @throws IOException if {@code f.toPath()} throws {@link InvalidPathException}.
*/
@Restricted(NoExternalUse.class)
public static @NonNull Path fileToPath(@NonNull File file) throws IOException {View on GitHub (pinned to 2e228ff40b)
Solutions
- Mask the mode value to 0777 before passing it: use mode & 0777 to strip setuid/setgid/sticky bits.
- If special bits are genuinely needed, handle them separately with native filesystem calls (e.g., chmod via ProcessBuilder) since Jenkins' POSIX permission API does not support them.
- Update the configuration input to only accept 3-digit octal values (000-777).
Example fix
// before Set<PosixFilePermission> perms = Util.modeToPermissions(02755); // after Set<PosixFilePermission> perms = Util.modeToPermissions(02755 & 0777); // strips setgid
Defensive patterns
Strategy: validation
Validate before calling
// Strip special bits before calling modeToPermissions int safeMode = mode & 0777; // removes setuid/setgid/sticky Set<PosixFilePermission> perms = Util.modeToPermissions(safeMode);
Try / catch
try {
Set<PosixFilePermission> perms = Util.modeToPermissions(mode);
} catch (IOException e) {
if (e.getMessage().startsWith("Invalid mode:")) {
// Retry with stripped special bits
perms = Util.modeToPermissions(mode & 0777);
} else {
throw e;
}
} Prevention
- Always mask mode values to 0777 before passing to modeToPermissions.
- Validate user-supplied chmod values in configuration forms to reject special bits.
- Document that setuid/setgid/sticky are unsupported in Jenkins permission APIs.
When it happens
Trigger: modeToPermissions is called with a mode like 02755 (setgid), 04755 (setuid), 01775 (sticky), or 07777 (all bits) — after masking with PERMISSIONS_MASK (07777), the result still has bits above MAX_SUPPORTED_MODE (0777), so the guard fails.
Common situations: Passing a raw Unix octal mode from a configuration field that allows setgid/setuid/sticky bits; copying a chmod value from system documentation that includes special bits; a plugin or configuration UI that accepts full numeric modes without filtering special bits.
Related errors
- Failed to mkdirs: ${remote}
- Failed to create a temporary directory in ${dir}
- Failed to set the timestamp of ${f} to ${timestamp}
- Failed to delete {0}
- Failed to fully read {0}
AI-assisted analysis of jenkinsci/jenkins@2e228ff40b (2026-08-14).
Data as JSON: /api/errors/029df4405e6e9069.
Report an issue: GitHub.