{"record":{"id":"d77db7e8cbc2b37b","repo":"alibaba/open-code-review","slug":"file-q-not-found-w","errorCode":null,"errorMessage":"file %q not found: %w","messagePattern":"file %q not found: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/tool/file_read.go","lineNumber":51,"sourceCode":"\t}\n\tif !hasEnd || endLine <= 0 {\n\t\tendLine = 0\n\t}\n\n\tmaxLines := fileReadMaxLines\n\tif endLine > 0 {\n\t\trequested := int(endLine) - int(startLine) + 1\n\t\tif requested <= 0 {\n\t\t\treturn \"\", fmt.Errorf(\"invalid line range: start_line %d is greater than end_line %d\", int(startLine), int(endLine))\n\t\t}\n\t\tif requested < maxLines {\n\t\t\tmaxLines = requested\n\t\t}\n\t}\n\n\tlines, totalLines, err := p.FileReader.ReadLines(ctx, filePath, int(startLine), maxLines)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"file %q not found: %w\", filePath, err)\n\t}\n\n\tif totalLines > 0 && int(startLine)-1 >= totalLines {\n\t\treturn \"\", fmt.Errorf(\"file %q has only %d lines, requested range %d-%d\", filePath, totalLines, int(startLine), int(endLine))\n\t}\n\n\teffectiveEnd := totalLines\n\tif endLine > 0 && int(endLine) < effectiveEnd {\n\t\teffectiveEnd = int(endLine)\n\t}\n\tfullRange := effectiveEnd - (int(startLine) - 1)\n\ttruncated := fullRange > fileReadMaxLines\n\n\tdisplayEnd := int(startLine) - 1 + len(lines)\n\n\tvar sb strings.Builder\n\tsb.WriteString(fmt.Sprintf(\"File: %s (Total lines: %d)\\n\", filePath, totalLines))\n\tsb.WriteString(fmt.Sprintf(\"IS_TRUNCATED: %t\\n\", truncated))","sourceCodeStart":33,"sourceCodeEnd":69,"githubUrl":"https://github.com/alibaba/open-code-review/blob/5cf97d0d15cbd41b602513c4be3bfec3cee5bf7f/internal/tool/file_read.go#L33-L69","documentation":"Wrapper error from FileReadProvider.Execute when FileReader.ReadLines fails for any reason (I/O error, path outside the repository, missing file, permission error). Note the wrapper unconditionally labels the cause 'not found', even when the underlying error is something else (e.g. 'outside repository' or a permissions failure), so always inspect the wrapped %w cause.","triggerScenarios":"Executing file_read with a file_path that does not exist, is a directory, is unreadable, lies outside the repo root, or whose symlink target cannot be resolved — i.e. any error propagated from ReadLines/readFromDisk/readLinesFromDisk.","commonSituations":"Agent hallucinating a file path; typo in the path; file deleted or renamed between listing and reading; trying to read an absolute path or ../ outside the repository; reading a file that only exists at a git ref in range/commit mode while the disk copy is absent.","solutions":["Check the exact path exists relative to the repository root (ls) and fix typos.","Inspect the wrapped cause after 'not found:' — if it says 'outside repository', use a repo-relative path instead of an absolute one.","Verify file permissions, and for range/commit modes confirm the file exists at the given ref (git show <ref>:<path>)."],"exampleFix":"// before: absolute path rejected/wrapped as not found\n{\"file_path\": \"/etc/hosts\"}\n// after: repository-relative path\n{\"file_path\": \"internal/tool/file_read.go\"}","handlingStrategy":"validation","validationCode":"rel, err := filepath.Rel(repoRoot, filePath)\nif err != nil || strings.HasPrefix(rel, \"..\") { return fmt.Errorf(\"path %q is not inside the repo\", filePath) }\nif _, err := os.Stat(filepath.Join(repoRoot, rel)); err != nil { return fmt.Errorf(\"file %q does not exist\", rel) }","typeGuard":"func insideRepo(repoRoot, p string) bool { rel, err := filepath.Rel(repoRoot, p); return err == nil && !strings.HasPrefix(rel, \"..\") }","tryCatchPattern":"out, err := provider.Execute(ctx, args)\nif err != nil && strings.Contains(err.Error(), \"not found\") {\n    // inspect wrapped cause; fall back to git-show read at HEAD\n    args[\"via_ref\"] = \"HEAD\"\n    out, err = provider.Execute(ctx, args)\n}","preventionTips":["Always pass repository-relative, not absolute, file paths.","Stat the path before reading to catch renames and deletions.","Remember the wrapper says 'not found' even for permission/outside-repo causes — parse the %w cause.","List directory contents via code_search or git ls-files instead of guessing paths."],"tags":["file-read","file-not-found","path-resolution","tool-execution"],"backgroundTag":"file-not-found","analyzedSha":"5cf97d0d15cbd41b602513c4be3bfec3cee5bf7f","analyzedAt":"2026-09-02T02:08:09.116Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}