apache/pulsar · error · IllegalArgumentException

Invalid filename:

Error message

Invalid filename: 

What it means

When a Python function is registered as a built-in function (the .py path starts with the 'builtin://' prefix) and the package URL type is not a supported remote URL, the filename must be a simple local name. If it contains '..' (path traversal), validation rejects it with IllegalArgumentException to prevent the function from referencing files outside the expected built-in directory.

Source

Thrown at pulsar-functions/utils/src/main/java/org/apache/pulsar/functions/utils/FunctionConfigUtils.java:895

        }
        if (functionConfig.getRetainKeyOrdering() != null
                && functionConfig.getRetainKeyOrdering()
                && functionConfig.getProcessingGuarantees() != null
                && functionConfig.getProcessingGuarantees() == FunctionConfig.ProcessingGuarantees.EFFECTIVELY_ONCE) {
            throw new IllegalArgumentException(
                    "When effectively once processing guarantee is specified, retain Key ordering cannot be set");
        }
        if (functionConfig.getRetainKeyOrdering() != null && functionConfig.getRetainKeyOrdering()
                && functionConfig.getRetainOrdering() != null && functionConfig.getRetainOrdering()) {
            throw new IllegalArgumentException("Only one of retain ordering or retain key ordering can be set");
        }

        if (!isEmpty(functionConfig.getPy()) && !org.apache.pulsar.common.functions.Utils
                .isFunctionPackageUrlSupported(functionConfig.getPy())
                && functionConfig.getPy().startsWith(BUILTIN)) {
            String filename = functionConfig.getPy();
            if (filename.contains("..")) {
                throw new IllegalArgumentException("Invalid filename: " + filename);
            }

            if (!new File(filename).exists()) {
                throw new IllegalArgumentException("The supplied python file does not exist");
            }
        }
        if (!isEmpty(functionConfig.getGo()) && !org.apache.pulsar.common.functions.Utils
                .isFunctionPackageUrlSupported(functionConfig.getGo())
                && functionConfig.getGo().startsWith(BUILTIN)) {
            String filename = functionConfig.getGo();
            if (filename.contains("..")) {
                throw new IllegalArgumentException("Invalid filename: " + filename);
            }

            if (!new File(filename).exists()) {
                throw new IllegalArgumentException("The supplied go file does not exist");
            }
        }

View on GitHub (pinned to 820761864e)

Solutions

  1. Remove any '..' segments from the .py value so the builtin filename is a bare name, e.g. 'builtin://myfunc.py'
  2. Use a fully qualified package URL (http(s)://, file://) supported by isFunctionPackageUrlSupported instead of a builtin reference
  3. Reference a built-in function by its exact registered name (list built-ins with the pulsar-admin functions builtins list)
  4. If this value comes from user input, sanitize/reject inputs containing '..' before building the config

Example fix

// before
conf.setPy("builtin://../functions/excerpt.py");
// after
conf.setPy("builtin://excerpt.py");
Defensive patterns

Strategy: validation

Validate before calling

String py = conf.getPy();
if (py != null && py.startsWith("builtin://")
        && !org.apache.pulsar.common.functions.Utils.isFunctionPackageUrlSupported(py)
        && py.substring("builtin://".length()).contains("..")) {
    throw new IllegalStateException("builtin python name must not contain '..'");
}

Type guard

boolean isSafeBuiltinName(String s) {
    return s != null && s.startsWith("builtin://") && !s.contains("..");
}

Try / catch

try {
    admin.functions().createFunction(conf);
} catch (IllegalArgumentException e) {
    if (e.getMessage().startsWith("Invalid filename:")) {
        conf.setPy("builtin://" + Paths.get(conf.getPy().replace("builtin://", "")).getFileName());
        admin.functions().createFunction(conf);
    } else throw e;
}

Prevention

When it happens

Trigger: Setting FunctionConfig.setPy() to something like 'builtin://../../etc/passwd' or any builtin reference whose filename component contains '..' while Utils.isFunctionPackageUrlSupported returns false for the value, then calling validateNonJavaFunction/validateJavaFunction (createFunction/updateFunction).

Common situations: Hand-assembling a builtin:// URL with relative path segments; attempting path traversal (intentionally or by string concatenation); typos like 'builtin://my/../func.py'; config generated by scripts that join paths with '../'.

Related errors


AI-assisted analysis of apache/pulsar@820761864e (2026-09-06). Data as JSON: /api/errors/a10c1c9b918a5ef8. Report an issue: GitHub.