juicedata/juicefs · error
worker config is missing source or destination
Error message
worker config is missing source or destination
What it means
After a successful JSON unmarshal, ReadClusterWorkerConfig validates that both Source and Destination are non-empty. If either is missing from the worker config payload it throws this error, since a worker cannot know what to sync. This guards against a manager sending a truncated or misconfigured payload.
Source
Thrown at pkg/sync/cluster.go:424
}
return shellescape.EscapeArgs(args), payload, nil
}
// ReadClusterWorkerConfig reads storage URLs and environment variables from worker stdin.
func ReadClusterWorkerConfig(r io.Reader) (string, string, map[string]string, error) {
data, err := io.ReadAll(io.LimitReader(r, maxClusterWorkerConfigSize+1))
if err != nil {
return "", "", nil, fmt.Errorf("read worker config: %s", err)
}
if len(data) > maxClusterWorkerConfigSize {
return "", "", nil, fmt.Errorf("worker config is too large")
}
var config clusterWorkerConfig
if err := json.Unmarshal(data, &config); err != nil {
return "", "", nil, fmt.Errorf("unmarshal worker config: %s", err)
}
if config.Source == "" || config.Destination == "" {
return "", "", nil, fmt.Errorf("worker config is missing source or destination")
}
return config.Source, config.Destination, config.Env, nil
}
func launchWorker(address string, config *Config, wg *sync.WaitGroup) {
workers := strings.Split(strings.Join(config.Workers, ","), ",")
for _, host := range workers {
wg.Add(1)
go func(host string) {
defer wg.Done()
// copy
path, err := findSelfPath()
if err != nil {
logger.Errorf("find self path: %s", err)
return
}
rpath := filepath.Join("/tmp", filepath.Base(path))
cmd := exec.Command("rsync", "-a", "-e", "ssh -o StrictHostKeyChecking=no -o PasswordAuthentication=no", path, host+":"+rpath)View on GitHub (pinned to c9a67b23e8)
Solutions
- Verify the manager's sync invocation includes both non-empty Source and Destination arguments
- Check manager-side logs for how clusterSource/clusterDestination were derived from the Config
- Ensure all nodes run compatible JuiceFS versions with matching clusterWorkerConfig field names
- If crafting test payloads, include both "source" and "destination" fields
Example fix
// before
{"env":{}} // worker rejects
// after
{"source":"s3://bucket/a","destination":"s3://bucket/b","env":{}} Defensive patterns
Strategy: validation
Validate before calling
var cfg struct {
Source string `json:"source"`
Destination string `json:"destination"`
Env map[string]string `json:"env"`
}
if err := json.Unmarshal(payload, &cfg); err == nil && (cfg.Source == "" || cfg.Destination == "") {
return fmt.Errorf("worker config is missing source or destination")
} Prevention
- Verify Source and Destination are non-empty before configuring a cluster sync
- Include both fields when hand-crafting worker test payloads
- Keep worker/manager payload schemas in version lockstep
When it happens
Trigger: A manager marshaled clusterWorkerConfig with empty Source or Destination (config.clusterSource/clusterDestination empty because Sync was called with missing/normalized-away URLs), or a hand-crafted/hijacked JSON payload with fields omitted (empty strings).
Common situations: Programmatic Config built without Source/Destination but with a Cluster specified; JSON produced by a different (incompatible) manager version using different field names; users manually piping test JSON lacking fields.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- read worker config: %s
- worker config is too large
- unmarshal worker config: %s
- errDirSuffix
- can't locate source or destination in command arguments
AI-assisted analysis of juicedata/juicefs@c9a67b23e8 (2026-09-06).
Data as JSON: /api/errors/6bba1f42cf149230.
Report an issue: GitHub.