wavetermdev/waveterm · error

cannot create directory %q: %w

Error message

cannot create directory %q: %w

What it means

RemoteFileTouchCommand wraps os.MkdirAll failure for the parent directory of the target file (created with 0755 before writing the file). Cause is permission denied, a path component being a file, or I/O errors.

Source

Thrown at pkg/wshrpc/wshremote/wshremote_file.go:424

				Dir:           computeDirPart(cleanedPath),
				Name:          filepath.Base(cleanedPath),
				StatError:     err.Error(),
				SupportsMkdir: true,
			}
			continue
		}
		rtn[path] = *fileInfo
	}
	return rtn, nil
}

func (impl *ServerImpl) RemoteFileTouchCommand(ctx context.Context, path string) error {
	cleanedPath := filepath.Clean(wavebase.ExpandHomeDirSafe(path))
	if _, err := os.Stat(cleanedPath); err == nil {
		return fmt.Errorf("file %q already exists", path)
	}
	if err := os.MkdirAll(filepath.Dir(cleanedPath), 0755); err != nil {
		return fmt.Errorf("cannot create directory %q: %w", filepath.Dir(cleanedPath), err)
	}
	if err := os.WriteFile(cleanedPath, []byte{}, 0644); err != nil {
		return fmt.Errorf("cannot create file %q: %w", cleanedPath, err)
	}
	return nil
}

func (impl *ServerImpl) RemoteFileMoveCommand(ctx context.Context, data wshrpc.CommandFileCopyData) error {
	destUri := data.DestUri
	srcUri := data.SrcUri

	destConn, err := connparse.ParseURIAndReplaceCurrentHost(ctx, destUri)
	if err != nil {
		return fmt.Errorf("cannot parse destination URI %q: %w", srcUri, err)
	}
	destPathCleaned := filepath.Clean(wavebase.ExpandHomeDirSafe(destConn.Path))
	_, err = os.Stat(destPathCleaned)
	if err == nil {

View on GitHub (pinned to a4447c1563)

Solutions

  1. Read the wrapped error to find which directory component failed.
  2. Ensure no ancestor path component is an existing file.
  3. Check write permission on the nearest existing ancestor.
  4. Create parent directories manually with correct permissions if 0755 is unsuitable.

Example fix

// before
wshclient.RemoteFileTouchCommand(ctx, "/srv/data/app/log.txt", nil)
// after
if _, err := wshclient.RemoteFileInfoCommand(ctx, "/srv/data/app", nil); err != nil {
    return fmt.Errorf("parent dir unavailable: %w", err)
}
wshclient.RemoteFileTouchCommand(ctx, "/srv/data/app/log.txt", nil)
Defensive patterns

Strategy: validation

Validate before calling

parent := filepath.Dir(path)
info, err := wshclient.RemoteFileInfoCommand(ctx, parent, nil)
if err == nil && !info.Dir { return fmt.Errorf("%s is a file, not a dir", parent) }

Try / catch

err := wshclient.RemoteFileTouchCommand(ctx, path, nil)
if err != nil && strings.Contains(err.Error(), "cannot create directory") {
    // inspect wrapped errno: EACCES / ENOTDIR
}

Prevention

When it happens

Trigger: Touching a path whose parent directory cannot be created: ancestor is an existing regular file, write permission missing, or read-only filesystem.

Common situations: Creating files under read-only mounts; path like /home/user/file.txt/sub/deep where file.txt is a file; permission-restricted home directories.

Understand the failure class

Background: mkdir permission denied (EACCES): failed to create directory errors explained — this error's family across 32 libraries.

Related errors


AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01). Data as JSON: /api/errors/fac4b6b37cdca8d7. Report an issue: GitHub.