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, nilView on GitHub (pinned to c9a67b23e8)
Solutions
- 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
- Check for normalization differences: print config.clusterSource/clusterDestination and compare to os.Args to find canonicalization (scheme case, trailing slash, percent-encoding) mismatches
- 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
- Always launch cluster sync via the juicefs sync CLI so source/destination are present in os.Args
- Avoid post-parsing normalization that changes the URL strings away from what was passed on the command line
- Log os.Args and the resolved clusterSource/clusterDestination when debugging cluster launch failures
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
- create %sor: %w
- marshal worker config: %s
- read worker config: %s
- worker config is too large
- unmarshal worker config: %s
AI-assisted analysis of juicedata/juicefs@c9a67b23e8 (2026-09-06).
Data as JSON: /api/errors/f58ed6fc203dd50b.
Report an issue: GitHub.