apache/beam · error · IllegalArgumentException

Provided Secret must be in the form projects/{project}/secre

Error message

Provided Secret must be in the form projects/{project}/secrets/{secret}/versions/{secret_version}

What it means

getSecret() accepts a Secret Manager resource name and validates it with SecretVersionName.isParsableFrom() before calling the Secret Manager API. If the string doesn't match projects/{project}/secrets/{secret}/versions/{version}, an IllegalArgumentException with the required format is thrown. It guards against malformed resource names hitting the GCP API.

Source

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

   * handled. For example, the kerberos factory can use this to download a krb5.conf and set a
   * system property.
   *
   * @throws IOException If downloading or processing the file fails.
   */
  protected void downloadAndProcessExtraFiles() throws IOException {
    // Default implementation should do nothing.
  }

  protected String getBaseDirectory() {
    return DIRECTORY_PREFIX;
  }

  protected byte[] getSecret(String secretVersion) {
    SecretVersionName secretVersionName;
    if (SecretVersionName.isParsableFrom(secretVersion)) {
      secretVersionName = SecretVersionName.parse(secretVersion);
    } else {
      throw new IllegalArgumentException(
          "Provided Secret must be in the form"
              + " projects/{project}/secrets/{secret}/versions/{secret_version}");
    }
    try (SecretManagerServiceClient client = SecretManagerServiceClient.create()) {
      AccessSecretVersionResponse response = client.accessSecretVersion(secretVersionName);
      return response.getPayload().getData().toByteArray();
    } catch (IOException e) {
      throw new RuntimeException(e);
    }
  }

  protected String processSecret(String originalValue, String secretId, byte[] secretValue) {
    // By Default, this will return the secret value directly. This function can be overridden by
    // derived classes.
    return new String(secretValue, StandardCharsets.UTF_8);
  }
}

View on GitHub (pinned to 12126d8942)

Solutions

  1. Use the fully qualified form: projects/PROJECT/secrets/SECRET/versions/VERSION (e.g. versions/latest)
  2. Validate the string with SecretVersionName.isParsableFrom(value) before configuring
  3. Build the name programmatically with SecretVersionName.of(project, secret, version).toString()
  4. Verify no whitespace or quotes leaked in from property files around the resource name

Example fix

// before
String secret = "projects/my-proj/secrets/kafka-keytab";
// after
String secret = "projects/my-proj/secrets/kafka-keytab/versions/latest";
Defensive patterns

Strategy: validation

Validate before calling

java
String SECRET_RE = "^projects/[^/]+/secrets/[^/]+/versions/[^/]+$";
if (!secretVersion.matches(SECRET_RE)) {
  throw new IllegalArgumentException("Bad secret version name: " + secretVersion);
}

Try / catch

java
try {
  byte[] keytab = factoryFn.getSecret(secret);
} catch (IllegalArgumentException e) {
  log.severe("Secret reference malformed: " + e.getMessage());
}

Prevention

When it happens

Trigger: A sasl.jaas.config keytab reference or other secret key contains a value like "my-secret" or "projects/p/secrets/s" (missing the versions segment) instead of the full 4-part SecretVersionName.

Common situations: Users pasting the secret ID instead of the full version resource name; omitting "versions/latest"; templating that dropped part of the path; mixing Secret Manager secret names with version names.

Understand the failure class

Background: "invalid id" errors: invalid identifier format — why libraries reject IDs before lookup, and how to fix them — this error's family across 37 libraries.

Related errors


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