pulumi/pulumi · error · fs.ErrNotExist
%w: %w
Error message
%w: %w
What it means
In the ACP filesystem ReadFileOverride path (pkg/cmd/pulumi/neo/acp/fs.go:101), when the editor-side read fails and the file also does not exist on local disk, the original editor error is wrapped with fs.ErrNotExist so callers see a standard not-found error. This satisfies the contract that missing files surface as errors.Is(err, fs.ErrNotExist), which the edit tool's creation mode depends on.
Source
Thrown at pkg/cmd/pulumi/neo/acp/fs.go:101
// ReadTextFile fetches the full content of an absolute path from the editor via
// the ACP `fs/read_text_file` request. Its signature matches
// tools.Filesystem.ReadFileOverride, so it can be assigned to that field
// directly, and it honors that field's contract of reporting missing files
// with an error satisfying errors.Is(err, fs.ErrNotExist).
func (c *ClientFS) ReadTextFile(ctx context.Context, path string) (string, error) {
var res readTextFileResult
if err := c.Caller.Call(ctx, "fs/read_text_file", readTextFileParams{
SessionID: c.SessionID,
Path: path,
}, &res); err != nil {
// ACP doesn't standardize a "file not found" error code, but the
// ReadFileOverride contract requires missing files to surface as
// fs.ErrNotExist (the edit tool's creation mode depends on it). The
// editor's view is local disk plus its open buffers, so when the editor
// couldn't read the file and it isn't on disk either, it doesn't exist.
if _, statErr := os.Stat(path); errors.Is(statErr, fs.ErrNotExist) {
return "", fmt.Errorf("%w: %w", fs.ErrNotExist, err)
}
return "", err
}
return res.Content, nil
}
View on GitHub (pinned to 793f7b2e16)
Solutions
- If creating a new file, this error is expected: proceed with the edit tool's creation mode, which checks for fs.ErrNotExist.
- Verify the path is correct and relative to the session's working directory; list the directory to confirm the intended file location.
- If the file should exist, refresh the editor's open buffers/revert unsaved state and retry — a stale buffer path can mask an on-disk rename or delete.
- Re-run the operation after the file is restored or the path corrected.
Example fix
// caller-side handling
content, err := readFile(path)
if errors.Is(err, fs.ErrNotExist) {
// create the file instead of editing
return createFile(path, newContent)
} Defensive patterns
Strategy: type-guard
Validate before calling
if _, err := os.Stat(path); errors.Is(err, fs.ErrNotExist) {
// file missing before the call: use edit-tool creation mode
} Type guard
func isFileNotFound(err error) bool { return errors.Is(err, fs.ErrNotExist) } Try / catch
content, err := reader.ReadFile(ctx, path)
if errors.Is(err, fs.ErrNotExist) {
return createFile(path, defaultContent)
}
if err != nil { return err } Prevention
- Confirm the path exists (or intentionally use creation mode) before editing
- Keep editor buffers in sync with disk; refresh after external renames/deletes
- Always match with errors.Is(err, fs.ErrNotExist), not string comparison
When it happens
Trigger: The edit tool attempts to read a file via the editor override, the editor reports failure, and os.Stat(path) confirms the file is absent — the returned error then wraps fs.ErrNotExist.
Common situations: Creating a brand-new file with the edit tool (expected path — creation mode relies on ErrNotExist), typos in file paths, or files deleted on disk but still shown open in the editor.
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
- opening log file: %w
- resolving working directory: %w
- stat on file %s: %w
- failed to open asset file '%v': %w
- not found
AI-assisted analysis of pulumi/pulumi@793f7b2e16 (2026-08-31).
Data as JSON: /api/errors/3d0bfa214effe25e.
Report an issue: GitHub.