apache/pulsar · error · IllegalArgumentException

Sink Archive file %s does not exist

Error message

Sink Archive file %s does not exist

What it means

After inferMissingArguments, if the archive is neither a supported package URL (file://, http://, package://) nor a builtin:// reference, the CLI treats it as a local file path and requires the file to exist, throwing this IllegalArgumentException otherwise.

Source

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

        protected Map<String, Object> parseConfigs(String str) throws JsonProcessingException {
            ObjectMapper mapper = ObjectMapperFactory.getMapper().getObjectMapper();
            TypeReference<HashMap<String, Object>> typeRef = new TypeReference<HashMap<String, Object>>() {};

            return mapper.readValue(str, typeRef);
        }

        protected void validateSinkConfigs(SinkConfig sinkConfig) {

            if (isBlank(sinkConfig.getArchive())) {
                throw new ParameterException("Sink archive not specified");
            }

            org.apache.pulsar.common.functions.Utils.inferMissingArguments(sinkConfig);

            if (!Utils.isFunctionPackageUrlSupported(sinkConfig.getArchive())
                    && !sinkConfig.getArchive().startsWith(Utils.BUILTIN)) {
                if (!new File(sinkConfig.getArchive()).exists()) {
                    throw new IllegalArgumentException(String.format("Sink Archive file %s does not exist",
                            sinkConfig.getArchive()));
                }
            }
        }

        protected String validateSinkType(String sinkType) throws IOException {
            Set<String> availableSinks;
            try {
                availableSinks = getAdmin().sinks().getBuiltInSinks().stream()
                        .map(ConnectorDefinition::getName).collect(Collectors.toSet());
            } catch (PulsarAdminException e) {
                throw new IOException(e);
            }

            if (!availableSinks.contains(sinkType)) {
                throw new ParameterException(
                        "Invalid sink type '" + sinkType + "' -- Available sinks are: " + availableSinks);
            }

View on GitHub (pinned to 820761864e)

Solutions

  1. Verify the path with `ls <archive>` and fix the --archive value
  2. Build the NAR first (mvn package) and point to the target/*.nar output
  3. Use a package:// URL or http:// location if the archive is not local

Example fix

// before
--archive ./sink.nar
// after
--archive /home/user/sink/target/sink-1.0.0.nar
Defensive patterns

Strategy: validation

Validate before calling

const fs = require('fs');
const archive = '/path/to/sink.nar';
if (!archive.startsWith('builtin://') && !/^(file|http|package):/.test(archive) && !fs.existsSync(archive)) {
  throw new Error(`Archive not found: ${archive}`);
}

Type guard

const archiveExists = (p) => p.startsWith('builtin://') || /^(file|http|package):/.test(p) || fs.existsSync(p);

Try / catch

try {
  // run sinks create
} catch (e) {
  if (e.message.includes('does not exist')) { /* fix archive path */ }
  throw e;
}

Prevention

When it happens

Trigger: Passing --archive with a relative/absolute local path that does not exist on the machine running the CLI (e.g. `--archive ./sink.nar` from the wrong directory, or the NAR was never built).

Common situations: Building the NAR in a different location than the CLI expects; running the command from another host/container where the file is absent; typo in the path.

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


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