apache/pulsar · error · IllegalArgumentException

Cannot parse sink-config

Error message

Cannot parse sink-config

What it means

The --sink-config string passed to the sink command could not be parsed into a Map via parseConfigs (JSON parsing). The CLI wraps the underlying exception in an IllegalArgumentException with this message, so the sink is never created.

Source

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

                resources.setRam(ram);
            }

            if (disk != null) {
                if (resources == null) {
                    resources = new Resources();
                }
                resources.setDisk(disk);
            }
            if (resources != null) {
                sinkConfig.setResources(resources);
            }

            try {
                if (null != sinkConfigString) {
                    sinkConfig.setConfigs(parseConfigs(sinkConfigString));
                }
            } catch (Exception ex) {
                throw new IllegalArgumentException("Cannot parse sink-config", ex);
            }

            if (autoAck != null) {
                sinkConfig.setAutoAck(autoAck);
            }
            if (timeoutMs != null) {
                sinkConfig.setTimeoutMs(timeoutMs);
            }
            if (negativeAckRedeliveryDelayMs != null && negativeAckRedeliveryDelayMs > 0) {
                sinkConfig.setNegativeAckRedeliveryDelayMs(negativeAckRedeliveryDelayMs);
            }

            if (customRuntimeOptions != null) {
                sinkConfig.setCustomRuntimeOptions(customRuntimeOptions);
            }

            if (secretsString != null) {
                Type type = new TypeToken<Map<String, Object>>() {}.getType();

View on GitHub (pinned to 820761864e)

Solutions

  1. Pass valid JSON: --sink-config '{"key":"value"}'
  2. Use --sink-config-file pointing to a valid JSON file to avoid shell quoting issues
  3. Validate the JSON with a parser (e.g. `jq .`) before running the command

Example fix

// before
--sink-config 'roots=localhost'
// after
--sink-config '{"roots":"localhost"}'
Defensive patterns

Strategy: validation

Validate before calling

const cfg = JSON.parse(sinkConfigString); // throws before invoking CLI if malformed
if (typeof cfg !== 'object' || Array.isArray(cfg)) throw new Error('sink-config must be a JSON object');

Type guard

const isJsonObject = (s) => { try { return !Array.isArray(JSON.parse(s)) && typeof JSON.parse(s) === 'object'; } catch { return false; } };

Try / catch

try {
  // run sinks create with --sink-config
} catch (e) {
  if (e.message.includes('Cannot parse sink-config')) { /* switch to --sink-config-file */ }
  throw e;
}

Prevention

When it happens

Trigger: Passing `--sink-config` with malformed JSON, e.g. `--sink-config 'key1=val1'` or single-quoted YAML instead of JSON like `'{"key":"value"}'`, or a JSON that parses to a non-map value.

Common situations: Shell quoting stripping inner double quotes (common with bash); using YAML config text in a JSON-expecting flag; trailing commas or unquoted keys in the JSON.

Related errors


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