wavetermdev/waveterm · error

failed to stat file: %w

Error message

failed to stat file: %w

What it means

ReadAppFile calls os.Stat on the resolved file path to get the modification time before reading. This error wraps a failed os.Stat (waveappstore.go:304-307). The dominant case is the file not existing (fs.ErrNotExist); it can also be a permission problem on a parent directory.

Source

Thrown at pkg/waveappstore/waveappstore.go:306

func ReadAppFile(appId string, fileName string) (*FileData, error) {
	if err := ValidateAppId(appId); err != nil {
		return nil, fmt.Errorf("invalid appId: %w", err)
	}

	appDir, err := GetAppDir(appId)
	if err != nil {
		return nil, err
	}

	filePath, err := validateAndResolveFilePath(appDir, fileName)
	if err != nil {
		return nil, err
	}

	fileInfo, err := os.Stat(filePath)
	if err != nil {
		return nil, fmt.Errorf("failed to stat file: %w", err)
	}

	contents, err := os.ReadFile(filePath)
	if err != nil {
		return nil, fmt.Errorf("failed to read file: %w", err)
	}

	return &FileData{
		Contents: contents,
		ModTs:    fileInfo.ModTime().UnixMilli(),
	}, nil
}

func DeleteAppFile(appId string, fileName string) error {
	if err := ValidateAppId(appId); err != nil {
		return fmt.Errorf("invalid appId: %w", err)
	}

View on GitHub (pinned to a4447c1563)

Solutions

  1. Check the wrapped error with errors.Is(err, fs.ErrNotExist) and treat it as 'file missing' rather than a hard failure.
  2. Verify the app exists first (waveappstore.ListAllAppFiles or os.Stat on waveappstore.GetAppDir(appId)).
  3. Confirm the namespace: 'draft/myapp' and 'local/myapp' are separate directories; the file may only exist in one.
  4. Fix the fileName spelling; path names are case-sensitive on Linux.

Example fix

// before
data, err := waveappstore.ReadAppFile(appId, fileName)
if err != nil { return err } // treats missing file as fatal

// after
data, err := waveappstore.ReadAppFile(appId, fileName)
if err != nil {
    if errors.Is(err, fs.ErrNotExist) {
        return nil, nil // file not written yet — handle as empty
    }
    return err
}
Defensive patterns

Strategy: try-catch

Validate before calling

func fileExists(appId, fileName string) bool {
    dir, err := waveappstore.GetAppDir(appId)
    if err != nil { return false }
    _, err = os.Stat(filepath.Join(dir, filepath.Clean(fileName)))
    return err == nil
}

Try / catch

data, err := waveappstore.ReadAppFile(appId, fileName)
if err != nil {
    if errors.Is(err, fs.ErrNotExist) {
        return nil, nil // treat as absent
    }
    return nil, err
}

Prevention

When it happens

Trigger: Calling ReadAppFile (or ReadAppFileCommand, generateBuilderAppData) for a fileName that does not exist inside the app directory, an app directory that does not exist yet, or a path whose parent dirs are unreadable.

Common situations: Reading a file from an app that was never created or was deleted; a typo in the file name; checking a file before WriteAppFile ever ran; reading across namespaces (draft vs local) where the file only exists in the other one.

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


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