apache/beam · error · IOException

Failed to download file

Error message

Failed to download file : %s

What it means

FileAwareFactoryFn rewrites Kafka configuration values that reference external files (MRS://{...} style placeholders) by downloading them to a local temp path and substituting the local path. If the download fails with IOException, it is rethrown as 'Failed to download file : <externalPath>'.

Solutions

  1. Verify the external path is correct and the object exists and is readable by the job's credentials
  2. Pre-download the file and reference a local path instead of the remote placeholder
  3. Check network access from workers (firewall/VPC) and that the temp directory is writable

Example fix

// before
"ssl.keystore.location": "mrs://mybucket/keystore.jks" // download fails on workers
// after
"ssl.keystore.location": "/opt/certs/keystore.jks" // pre-staged on workers
Defensive patterns

Strategy: retry

Validate before calling

boolean reachable = false; try (InputStream in = new URL(stripScheme(externalPath)).openStream()) { reachable = true; } catch (IOException e) { LOG.error("External file unreachable: {}", externalPath); }

Try / catch

try { apply(configValue); } catch (IOException e) { if (e.getMessage().startsWith("Failed to download file")) { /* check path/credentials/network, retry with backoff */ } else throw e; }

Prevention

When it happens

Trigger: A config value contains an external-file placeholder whose URL is unreachable, credentials are missing, the bucket/path does not exist, or the local temp directory is not writable during apply().

Common situations: Kafka connectors configured with remote keystore/truststore files (e.g. in GCS) where the path was mistyped, permissions/credentials are absent, or the worker cannot reach the storage endpoint (VPC/no internet).

Related errors


AI-assisted analysis of apache/beam@12126d8942 (2026-09-13). Data as JSON: /api/errors/72b204da889182f3. Report an issue: GitHub.

Appendix: source

Thrown at sdks/java/extensions/kafka-factories/src/main/java/org/apache/beam/sdk/extensions/kafka/factories/FileAwareFactoryFn.java:130

          value = e.getValue();
          if (value instanceof String) {
            String originalValue = (String) value;
            Matcher matcher = PATH_PATTERN.matcher(originalValue);
            StringBuffer sb = new StringBuffer();

            while (matcher.find()) {
              String externalPath = matcher.group(1);
              String secretValue = matcher.group(2);
              String secretFile = matcher.group(3);

              if (externalPath != null) {
                try {
                  String tmpPath = replacePathWithLocal(externalPath);
                  String localPath = downloadExternalFile(externalPath, tmpPath);
                  matcher.appendReplacement(sb, Matcher.quoteReplacement(localPath));
                  LOG.info("Downloaded {} to {}", externalPath, localPath);
                } catch (IOException io) {
                  throw new IOException("Failed to download file : " + externalPath, io);
                }
              } else if (secretValue != null) {
                try {
                  String secretId = secretValue.substring(SECRET_VALUE_PREFIX.length());
                  String processedSecret =
                      processSecret(originalValue, secretId, getSecretWithCache(secretId));

                  matcher.appendReplacement(sb, Matcher.quoteReplacement(processedSecret));
                } catch (IllegalArgumentException ia) {
                  throw new IllegalArgumentException("Failed to get secret.", ia);
                }
              } else if (secretFile != null) {
                throw new UnsupportedOperationException("Not yet implemented.");
              }
            }
            matcher.appendTail(sb);
            String processedValue = sb.toString();
            processedConfig.put(key, processedValue);

View on GitHub (pinned to 12126d8942)