plandex-ai/plandex · error

failed to read file: %w

Error message

failed to read file: %w

What it means

Inside the stream TUI's checkMissingFile handler, os.ReadFile on msg.MissingFilePath failed, so the model records this error and quits the TUI. The user was asked to provide a file that the plan expects but that could not be read from disk.

Source

Thrown at app/cli/stream_tui/update.go:688

		log.Println("checkMissingFile - received missing file message | path:", msg.MissingFilePath)

		if msg.MissingFileAutoContext {
			log.Println("checkMissingFile - received missing file message | auto context")
			m.updateState(func() {
				m.processing = true
				m.autoLoadedMissingFile = true
			})

			return m, tea.Batch(
				func() tea.Msg {
					<-m.sharedTicker.C
					return spinner.TickMsg{}
				},
				func() tea.Msg {
					bytes, err := os.ReadFile(msg.MissingFilePath)
					if err != nil {
						log.Println("failed to read file:", err)
						m.err = fmt.Errorf("failed to read file: %w", err)
						return tea.Quit
					}
					content := string(shared.NormalizeEOL(bytes))

					log.Println("checkMissingFile - calling RespondMissingFile")
					apiErr := api.Client.RespondMissingFile(lib.CurrentPlanId, lib.CurrentBranch, shared.RespondMissingFileRequest{
						Choice:   shared.RespondMissingFileChoiceLoad,
						FilePath: msg.MissingFilePath,
						Body:     content,
					})

					if apiErr != nil {
						log.Println("missing file prompt api error:", apiErr)
						m.updateState(func() {
							m.apiErr = apiErr
						})
						return tea.Quit
					}

View on GitHub (pinned to e2d772072e)

Solutions

  1. Check the path printed in the log line 'failed to read file:' — verify it exists with ls
  2. Re-enter the missing-file prompt with an absolute path
  3. Check file permissions (read access for the running user)
  4. Restore or recreate the deleted file before responding to the prompt

Example fix

// before
bytes, err := os.ReadFile(msg.MissingFilePath)
// after
if _, statErr := os.Stat(msg.MissingFilePath); statErr != nil {
    log.Printf("missing file not readable: %v", statErr)
    return spinner.TickMsg{} // re-prompt instead of quitting
}
bytes, err := os.ReadFile(msg.MissingFilePath)
Defensive patterns

Strategy: validation

Validate before calling

if fi, err := os.Stat(path); err != nil || fi.IsDir() {
    // path missing or a directory — fix before responding to the prompt
}
if fi, err := os.Stat(path); err == nil && fi.Mode().Perm()&0o400 == 0 {
    // not readable by current user
}

Try / catch

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

Prevention

When it happens

Trigger: A tea.Msg command reads msg.MissingFilePath with os.ReadFile; the path doesn't exist, was deleted/moved between prompt and read, or the process lacks read permission.

Common situations: User typed a wrong path at the missing-file prompt, the file was deleted after being referenced, or a relative path was entered from a different working directory than the TUI expects.

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.

Related errors


AI-assisted analysis of plandex-ai/plandex@e2d772072e (2026-09-05). Data as JSON: /api/errors/1dcde4464d6cf445. Report an issue: GitHub.