apache/pulsar · error · RuntimeException

Fully qualified function names (FQFNs) must be of the form t

Error message

Fully qualified function names (FQFNs) must be of the form tenant/namespace/name

What it means

When --fqfn is used, CmdFunctions splits it on '/' and requires exactly three parts: tenant, namespace, and function name. An FQFN with a different number of segments throws a RuntimeException describing the required tenant/namespace/name form.

Source

Thrown at pulsar-client-tools/src/main/java/org/apache/pulsar/admin/cli/CmdFunctions.java:150

        protected String namespace;

        @Option(names = "--name", description = "The name of a Pulsar Function")
        protected String functionName;

        @Override
        void processArguments() throws Exception {
            boolean usesSetters = (null != tenant || null != namespace || null != functionName);
            boolean usesFqfn = (null != fqfn);

            // Throw an exception if --fqfn is set alongside any combination of --tenant, --namespace, and --name
            if (usesFqfn && usesSetters) {
                throw new RuntimeException("You must specify either a Fully Qualified Function Name (FQFN) "
                        + "or tenant, namespace, and function name");
            } else if (usesFqfn) {
                // If the --fqfn flag is used, parse tenant, namespace, and name using that flag
                String[] fqfnParts = fqfn.split("/");
                if (fqfnParts.length != 3) {
                    throw new RuntimeException(
                            "Fully qualified function names (FQFNs) must be of the form tenant/namespace/name");
                }
                tenant = fqfnParts[0];
                namespace = fqfnParts[1];
                functionName = fqfnParts[2];
            } else {
                if (tenant == null) {
                    tenant = PUBLIC_TENANT;
                }
                if (namespace == null) {
                    namespace = DEFAULT_NAMESPACE;
                }
                if (null == functionName) {
                    throw new RuntimeException(
                            "You must specify a name for the function or a Fully Qualified Function Name (FQFN)");
                }
            }
        }

View on GitHub (pinned to 820761864e)

Solutions

  1. Supply the full three-part FQFN: --fqfn tenant/namespace/functionName.
  2. Count the '/' separators — exactly two are allowed.
  3. Alternatively use --tenant/--namespace/--name explicitly instead of --fqfn.

Example fix

// before
pulsar-admin functions get --fqfn public/default
// after
pulsar-admin functions get --fqfn public/default/myfunc
Defensive patterns

Strategy: validation

Validate before calling

if (fqfn != null) {
    String[] parts = fqfn.split("/");
    if (parts.length != 3 || fqfn.startsWith("/") || fqfn.endsWith("/")) {
        throw new IllegalArgumentException("FQFN must be tenant/namespace/name: " + fqfn);
    }
}

Try / catch

try {
    admin.functions().getFunction(tenant, ns, name);
} catch (RuntimeException e) {
    if (e.getMessage().contains("tenant/namespace/name")) {
        System.err.println("Malformed FQFN; expected exactly two '/' separators.");
    }
}

Prevention

When it happens

Trigger: Passing --fqfn values like 'public/default' (missing name), 'public/default/ex/extra', or an empty/garbled string so split('/') yields != 3 parts.

Common situations: Truncating an FQFN copied from a UI, including a topic-like extra segment, or using backslashes instead of forward slashes on Windows shells.

Related errors


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