wavetermdev/waveterm · error
failed to create socket directory: %w
Error message
failed to create socket directory: %w
What it means
MakeJobDomainSocket creates the per-user socket directory /tmp/waveterm-<uid> with os.MkdirAll(0700) before binding the job's domain socket. This error wraps any MkdirAll failure. It almost always means a filesystem/permission problem on /tmp rather than a bug in the caller.
Source
Thrown at pkg/jobmanager/jobmanager.go:383
if err != nil {
return fmt.Errorf("failed to attach stream writer: %w", err)
}
err = jm.StreamManager.SetRwndSize(int(jm.pendingStreamMeta.RWnd))
if err != nil {
return fmt.Errorf("failed to set rwnd size: %w", err)
}
log.Printf("StartStream: streamid=%s rwnd=%d streaming started\n", jm.pendingStreamMeta.Id, jm.pendingStreamMeta.RWnd)
jm.pendingStreamMeta = nil
return nil
}
func MakeJobDomainSocket(clientId string, jobId string) error {
socketDir := filepath.Join("/tmp", fmt.Sprintf("waveterm-%d", os.Getuid()))
err := os.MkdirAll(socketDir, 0700)
if err != nil {
return fmt.Errorf("failed to create socket directory: %w", err)
}
socketPath := wavebase.GetRemoteJobSocketPath(jobId)
os.Remove(socketPath)
listener, err := net.Listen("unix", socketPath)
if err != nil {
return fmt.Errorf("failed to listen on domain socket: %w", err)
}
go func() {
defer func() {
panichandler.PanicHandler("MakeJobDomainSocket:accept", recover())
listener.Close()
os.Remove(socketPath)
}()
for {View on GitHub (pinned to a4447c1563)
Solutions
- Check whether /tmp/waveterm-<uid> exists as a file and remove it: ls -la /tmp | grep waveterm
- Verify /tmp is writable for the running uid; free space if ENOSPC
- Set TMPDIR to a writable directory if the environment restricts /tmp (if the code honors it; otherwise fix mounts)
- Inspect the wrapped error for EACCES/EROFS/ENOSPC and fix the corresponding mount/permission
Example fix
// before
if err := os.MkdirAll(socketDir, 0700); err != nil {
return fmt.Errorf("failed to create socket directory: %w", err)
}
// after
if err := os.MkdirAll(socketDir, 0700); err != nil {
if fi, serr := os.Lstat(socketDir); serr == nil && !fi.IsDir() {
if rmErr := os.Remove(socketDir); rmErr == nil {
return MakeJobDomainSocket(clientId, jobId)
}
}
return fmt.Errorf("failed to create socket directory %s: %w", socketDir, err)
} Defensive patterns
Strategy: try-catch
Validate before calling
sd := fmt.Sprintf("/tmp/waveterm-%d", os.Getuid())
if fi, err := os.Stat("/tmp"); err != nil || !fi.IsDir() {
return fmt.Errorf("/tmp unavailable")
}
if fi, err := os.Lstat(sd); err == nil && !fi.IsDir() {
return fmt.Errorf("%s exists and is not a directory", sd)
} Try / catch
if err := MakeJobDomainSocket(clientId, jobId); err != nil {
if strings.HasPrefix(err.Error(), "failed to create socket directory") {
log.Printf("socket dir error: %v", errors.Unwrap(err))
// check /tmp writability, ENOSPC, or blocking file
}
return err
} Prevention
- Pre-flight check that /tmp is writable for the current uid
- Clean stale /tmp/waveterm-<uid> entries (especially files masquerading as directories) at startup
- Monitor tmpfs/disk space in containers
- Inspect the wrapped errno (EACCES/EROFS/ENOSPC) to target the right fix
When it happens
Trigger: os.MkdirAll("/tmp/waveterm-<uid>", 0700) fails because /tmp is not writable, the path exists as a regular file, the filesystem is full or read-only, or a path component denies traversal.
Common situations: Container with read-only /tmp; sticky-bit /tmp with restrictive mount options; leftover regular file named waveterm-<uid> in /tmp; disk-full (ENOSPC) on tmpfs; SELinux/AppArmor denial.
Understand the failure class
Background: mkdir permission denied (EACCES): failed to create directory errors explained — this error's family across 32 libraries.
Related errors
- error creating listener at %v: %v
- failed to create backup directory: %w
- failed to listen on domain socket: %w
- failed to create log directory: %w
- failed to open log file: %w
AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01).
Data as JSON: /api/errors/78235d57abada85c.
Report an issue: GitHub.