apache/pulsar · error · RuntimeException

You must specify either a Fully Qualified Function Name (FQF

Error message

You must specify either a Fully Qualified Function Name (FQFN) or tenant, namespace, and function name

What it means

CmdFunctions.processArguments enforces mutually exclusive function identification: either --fqfn alone, or --tenant/--namespace/--name. If --fqfn is combined with any of the individual setters, a RuntimeException is thrown because the two identification methods could conflict.

Source

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

        protected String fqfn;

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

        @Option(names = "--namespace", description = "The namespace of a Pulsar Function")
        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;
                }

View on GitHub (pinned to 820761864e)

Solutions

  1. Remove --tenant/--namespace/--name and rely solely on --fqfn tenant/namespace/name.
  2. Or drop --fqfn and keep the explicit --tenant, --namespace, --name options.

Example fix

// before
pulsar-admin functions delete --tenant public --namespace default --name ex --fqfn public/default/ex
// after
pulsar-admin functions delete --fqfn public/default/ex
Defensive patterns

Strategy: validation

Validate before calling

if (fqfn != null && (tenant != null || namespace != null || name != null)) {
    throw new IllegalArgumentException("Use either --fqfn or --tenant/--namespace/--name, not both");
}

Try / catch

try {
    functionsAdmin.delete(fqfnOrParams...);
} catch (RuntimeException e) {
    if (e.getMessage().contains("FQFN")) {
        System.err.println("Specify identification one way: --fqfn alone, or tenant+namespace+name.");
    }
}

Prevention

When it happens

Trigger: Invoking any pulsar-functions subcommand (create, update, delete, get, etc.) with --fqfn together with --tenant, --namespace, or --name on the command line.

Common situations: Scripting a command that previously used tenant/namespace/name and adding --fqfn for clarity, or expanding an alias that already contained the individual options.

Related errors


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