juicedata/juicefs · error

can't locate source or destination in command arguments

Error message

can't locate source or destination in command arguments

What it means

prepareWorkerCommand builds the SSH command line for a distributed-sync worker by scanning the manager's own os.Args for the source and destination storage URLs so they can be redacted (passwords removed) in the worker argv. If neither (or either) of the configured clusterSource/clusterDestination strings appears verbatim in the process arguments, the manager refuses to launch the worker and throws this error rather than leaking credentials or launching a worker with wrong storage targets.

Source

Thrown at pkg/sync/cluster.go:389

	}
	return "", fmt.Errorf("can't find path for %s", program)
}

func prepareWorkerCommand(host, address, path string, config *Config) ([]string, []byte, error) {
	workerArgs := append([]string(nil), os.Args[1:]...)
	var foundSource, foundDestination bool
	for i, arg := range workerArgs {
		if arg == config.clusterSource {
			workerArgs[i] = utils.RemovePassword(config.clusterSource)
			foundSource = true
		}
		if arg == config.clusterDestination {
			workerArgs[i] = utils.RemovePassword(config.clusterDestination)
			foundDestination = true
		}
	}
	if !foundSource || !foundDestination {
		return nil, nil, fmt.Errorf("can't locate source or destination in command arguments")
	}

	payload, err := json.Marshal(clusterWorkerConfig{
		Source:      config.clusterSource,
		Destination: config.clusterDestination,
		Env:         config.Env,
	})
	if err != nil {
		return nil, nil, fmt.Errorf("marshal worker config: %s", err)
	}

	args := []string{host, path}
	args = append(args, workerArgs...)
	args = append(args, "--manager", address)
	if !config.Verbose && !config.Quiet {
		args = append(args, "-q")
	}
	return shellescape.EscapeArgs(args), payload, nil

View on GitHub (pinned to c9a67b23e8)

Solutions

  1. Ensure the exact source and destination URL strings given to Sync appear verbatim in the process command-line arguments (os.Args) — pass them as CLI flags, not only in the Config struct
  2. Check for normalization differences: print config.clusterSource/clusterDestination and compare to os.Args to find canonicalization (scheme case, trailing slash, percent-encoding) mismatches
  3. If invoking sync programmatically, run cluster sync via the CLI entrypoint so argv contains both URLs, or patch the code to populate workerArgs from config instead of os.Args

Example fix

// before (programmatic call, argv lacks URLs)
cfg := &sync.Config{Source: "s3://bucket/a", Destination: "s3://bucket/b", Cluster: "..."}
sync.Sync(cfg) // -> can't locate source or destination in command arguments

// after (run through CLI so argv contains both URLs)
juicefs sync s3://bucket/a s3://bucket/b --cluster worker1,worker2
Defensive patterns

Strategy: validation

Validate before calling

for _, arg := range os.Args[1:] {
	if arg == cfg.Source {
		foundSrc = true
	}
	if arg == cfg.Destination {
		foundDst = true
	}
}
if !foundSrc || !foundDst {
	return fmt.Errorf("source %q / destination %q must appear verbatim in command args for cluster sync", cfg.Source, cfg.Destination)
}

Prevention

When it happens

Trigger: juicefs sync --cluster is run and the source or destination URL passed on the command line differs from config.clusterSource/clusterDestination — e.g. the URLs were normalized after flag parsing (path cleanup, scheme canonicalization), aliases/relpaths resolved, or flags set programmatically rather than via argv.

Common situations: Launching cluster sync programmatically (SDK/tests) with a Config whose Source/Destination never appear in os.Args; passing URLs that get rewritten (trailing slashes, escaped chars); running via a wrapper that rewrites argv; source or destination given as a local path that was converted to a canonical URI.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


AI-assisted analysis of juicedata/juicefs@c9a67b23e8 (2026-09-06). Data as JSON: /api/errors/f58ed6fc203dd50b. Report an issue: GitHub.