juicedata/juicefs · error
read worker config: %s
Error message
read worker config: %s
What it means
ReadClusterWorkerConfig reads the worker config (storage URLs + env) that the manager pipes over the worker's stdin. This error wraps any failure reading that stdin stream (io.ReadAll on a limited reader), e.g. the pipe was closed early or the reader returned an I/O error.
Source
Thrown at pkg/sync/cluster.go:414
})
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
}
// 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)View on GitHub (pinned to c9a67b23e8)
Solutions
- Re-run the sync and check the manager side for crashes or network drops
- Verify the SSH transport to workers is stable (no aggressive timeouts, keepalives enabled)
- Check that nothing else consumes or closes the worker's stdin (shell redirections, wrapper scripts)
- If persistent, inspect disk/OS-level pipe errors on the worker host
Example fix
// before (wrapper consuming stdin) ssh worker 'somecmd | juicefs sync ...' // after (pass manager payload via stdin untouched) ssh worker 'juicefs sync ... --manager host:port' < config.json
Defensive patterns
Strategy: try-catch
Try / catch
src, dst, env, err := sync.ReadClusterWorkerConfig(os.Stdin)
if err != nil {
if strings.Contains(err.Error(), "read worker config") {
logger.Fatalf("worker stdin transport failed: %v — check manager liveness and SSH stability", err)
}
logger.Fatalf("worker config error: %v", err)
} Prevention
- Don't redirect or consume the worker's stdin with wrappers or pipelines
- Ensure the manager host and network are stable during worker startup
- Monitor SSH keepalive/timeout settings for long cluster syncs
When it happens
Trigger: The worker process's stdin pipe errors or is closed prematurely before EOF while ReadClusterWorkerConfig reads up to maxClusterWorkerConfigSize+1 bytes — e.g. manager died mid-write, SSH connection dropped, or a broken pipe on the transport.
Common situations: SSH connection to the manager drops during cluster sync startup; the manager process is killed while launching workers; stdin redirected from a file/pipe that errors or is already closed.
Understand the failure class
Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.
Related errors
- worker config is too large
- unmarshal worker config: %s
- worker config is missing source or destination
- closed
- can't locate source or destination in command arguments
AI-assisted analysis of juicedata/juicefs@c9a67b23e8 (2026-09-06).
Data as JSON: /api/errors/112ab4bd3599bc26.
Report an issue: GitHub.