wavetermdev/waveterm · error
failed to start job: %w
Error message
failed to start job: %w
What it means
StartJob builds the job's command via MakeJobCmd(jm.JobId, cmdDef). If command construction fails (invalid command definition, working directory, environment marshaling, or pty setup inputs), the failure is wrapped as 'failed to start job'. The job manager state (jm.Cmd) is left unset.
Source
Thrown at pkg/jobmanager/jobmanager.go:241
jm.lock.Lock()
defer jm.lock.Unlock()
if jm.Cmd != nil {
log.Printf("StartJob: job already started")
return nil, fmt.Errorf("job already started")
}
cmdDef := CmdDef{
Cmd: data.Cmd,
Args: data.Args,
Env: data.Env,
TermSize: data.TermSize,
}
log.Printf("StartJob: creating job cmd for jobid=%s", jm.JobId)
jobCmd, err := MakeJobCmd(jm.JobId, cmdDef)
if err != nil {
log.Printf("StartJob: failed to make job cmd: %v", err)
return nil, fmt.Errorf("failed to start job: %w", err)
}
jm.Cmd = jobCmd
log.Printf("StartJob: job cmd created successfully")
if data.StreamMeta != nil {
serverSeq, err := jm.connectToStreamHelper_withlock(msc, *data.StreamMeta, 0)
if err != nil {
return nil, fmt.Errorf("failed to connect stream: %w", err)
}
err = msc.WshRpc.StreamBroker.AttachStreamWriter(data.StreamMeta, jm.StreamManager)
if err != nil {
return nil, fmt.Errorf("failed to attach stream writer: %w", err)
}
log.Printf("StartJob: connected stream streamid=%s serverSeq=%d\n", data.StreamMeta.Id, serverSeq)
}
cmd, cmdPty := jobCmd.GetCmd()
if cmdPty != nil {View on GitHub (pinned to a4447c1563)
Solutions
- Check the log line 'StartJob: failed to make job cmd' for the wrapped inner cause
- Validate data.Cmd is a non-empty, resolvable command path and Args/Env are well-formed before calling StartJob
- Use an absolute command path if the daemon's PATH differs from the user's shell PATH
- If TermSize is supplied, ensure Width/Height are positive
Example fix
// before
startData := wshrpc.CommandStartJobData{Cmd: userTypedCmd}
// after
if userTypedCmd == "" {
return fmt.Errorf("cmd is required")
}
cmdPath, err := exec.LookPath(userTypedCmd)
if err != nil {
return fmt.Errorf("command %q not found: %w", userTypedCmd, err)
}
startData := wshrpc.CommandStartJobData{Cmd: cmdPath} Defensive patterns
Strategy: validation
Validate before calling
if data.Cmd == "" {
return fmt.Errorf("Cmd is required")
}
if _, err := exec.LookPath(data.Cmd); err != nil {
return fmt.Errorf("Cmd %q not found on daemon PATH: %w", data.Cmd, err)
}
if data.TermSize != nil && (data.TermSize.Rows <= 0 || data.TermSize.Cols <= 0) {
return fmt.Errorf("TermSize must be positive")
} Try / catch
rtn, err := jm.StartJob(msc, startData)
if err != nil {
var inner error
if errors.Unwrap(err) != nil { inner = errors.Unwrap(err) }
log.Printf("start failed: %v (cause: %v)", err, inner)
return err
} Prevention
- Validate Cmd/Args/Env/TermSize before submitting StartJob
- Use absolute command paths to avoid daemon PATH differences
- Log MakeJobCmd's inner error (also in jm logs) for the real cause
- Test job definitions with a dry-run LookPath check
When it happens
Trigger: CommandStartJobData with an empty/missing Cmd, unresolvable command name, invalid Env map or TermSize values that MakeJobCmd cannot translate into a valid exec.Cmd.
Common situations: Typo in the command name or command not on PATH at daemon time; empty cmd string from a UI submitting a blank form; environment variables containing values MakeJobCmd cannot serialize.
Related errors
- Image too large (>5MB)
- Unsupported or invalid image type: ${blob.type}
- Invalid CSS color: ${String(color)}
- Invalid CSS color: ${color}
- ai:model is required
AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01).
Data as JSON: /api/errors/0c06d4e86e422dc8.
Report an issue: GitHub.