apache/flink · error · FlinkException
The discovery script %s is not executable.
Error message
The discovery script %s is not executable.
What it means
Thrown by GPUDriver when the GPU discovery script file exists but the JVM sees it as non-executable (File.canExecute() == false). This is a filesystem permission check done after the existence check in the constructor, so it only fires once the path itself is correct.
Source
Thrown at flink-external-resources/flink-external-resource-gpu/src/main/java/org/apache/flink/externalresource/gpu/GPUDriver.java:89
}
Path discoveryScriptPath = Paths.get(discoveryScriptPathStr);
if (!discoveryScriptPath.isAbsolute()) {
discoveryScriptPath =
Paths.get(
System.getenv().getOrDefault(ConfigConstants.ENV_FLINK_HOME_DIR, "."),
discoveryScriptPathStr);
}
discoveryScriptFile = discoveryScriptPath.toFile();
if (!discoveryScriptFile.exists()) {
throw new FileNotFoundException(
String.format(
"The gpu discovery script does not exist in path %s.",
discoveryScriptFile.getAbsolutePath()));
}
if (!discoveryScriptFile.canExecute()) {
throw new FlinkException(
String.format(
"The discovery script %s is not executable.",
discoveryScriptFile.getAbsolutePath()));
}
args = config.get(DISCOVERY_SCRIPT_ARG);
}
@Override
public Set<GPUInfo> retrieveResourceInfo(long gpuAmount) throws Exception {
Preconditions.checkArgument(
gpuAmount > 0,
"The gpuAmount should be positive when retrieving the GPU resource information.");
final Set<GPUInfo> gpuResources = new HashSet<>();
String output = executeDiscoveryScript(discoveryScriptFile, gpuAmount, args);
if (!output.isEmpty()) {
String[] indexes = output.split(",");View on GitHub (pinned to 2f3c205e92)
Solutions
- Run 'chmod +x <script>' on every TaskManager node (see the absolute path in the error message)
- For Kubernetes ConfigMaps, set defaultMode to 0755 on the volume mount
- Copy files with 'cp -p' or 'rsync -p' / extract with 'tar -p' to preserve the execute bit
- Verify with 'sudo -u <flink-user> test -x <script> && echo ok'
Example fix
# before $ ls -l /opt/flink/scripts/gpu-discovery.sh -rw-r--r-- 1 flink flink 512 ... # after $ chmod +x /opt/flink/scripts/gpu-discovery.sh $ ls -l /opt/flink/scripts/gpu-discovery.sh -rwxr-xr-x 1 flink flink 512 ...
Defensive patterns
Strategy: validation
Validate before calling
java.io.File f = new java.io.File(scriptPath);
if (f.exists() && !f.canExecute()) {
throw new IllegalStateException("Make the GPU discovery script executable: chmod +x " + f.getAbsolutePath());
} Prevention
- Run chmod +x in the Dockerfile after copying scripts
- Set defaultMode: 0755 on Kubernetes ConfigMap volume mounts
- Include a permissions smoke test in the container entrypoint
When it happens
Trigger: Constructing GPUDriver with a discovery script whose execute bit is not set for the user running the TaskManager JVM: chmod missing, file copied without preserving permissions, or a read-only mount (some Docker volumes, ConfigMaps in Kubernetes) that drops the +x bit.
Common situations: Kubernetes ConfigMap volumes mount files as 0644 by default; extracting a tarball as root and running Flink as another user; scripts edited/re-uploaded via a tool that resets permissions.
Related errors
- The gpu discovery script does not exist in path %s.
- Error parsing YAML configuration.
- File {} does not exist or the user running Flink ('{}') has
- The discovery script executed for over %d ms.
- Discovery script exit with non-zero return code: %s.
AI-assisted analysis of apache/flink@2f3c205e92 (2026-08-14).
Data as JSON: /api/errors/23b2812916ace418.
Report an issue: GitHub.