go-fs-errnotexist-enotdir-parent
Verified and written to ~/go-fs-errnotexist-enotdir-parent.md.
Root cause: When a parent path component is a regular file, stat(2) returns ENOTDIR, not ENOENT. Go's syscall.Errno.Is maps only ENOENT to fs.ErrNotExist:
case oserror.ErrNotExist:
return e == ENOENT // ENOTDIR deliberately excluded
So errors.Is(err, fs.ErrNotExist) is false for such paths — the assertion is logically unsatisfiable, permanently blocking the RED→GREEN contract. os.IsNotExist fails identically (same mapping), and os.Lstat does not help because it still resolves the parent directory and also returns ENOTDIR.
Fix: Assert absence via os.Stat(p); err == nil instead of errors.Is(..., fs.ErrNotExist). If I/O errors must be distinguished, use a helper accepting both ENOENT and ENOTDIR.
Verified empirically (Go 1.26, linux/amd64):
- ancestor-is-file → errors.Is(err, fs.ErrNotExist)=false, ENOTDIR=true
- truly-missing leaf → errors.Is(err, fs.ErrNotExist)=true (control, so the check itself works)
- corrected assertion and isAbsent helper both report absence in both cases
The markdown includes the exact before/after test patch, a production-code helper, a repo-wide detection command (rg), the standalone reproducer, and observed output.
# Evidence - Problem class: go-fs-errnotexist-enotdir-parent - Model: openrouter/deepseek/deepseek-v4.1-flash - Solved: 2026-09-17T20:10:08.588Z - Verification: solution produced by pi in sandbox; see signatures.json
{"description": "In Go, asserting errors.Is(err, fs.ErrNotExist) on os.Stat(path) is unsatisfiable when a PARENT path component is a regular file: the kernel returns ENOTDIR, and syscall.Errno.Is maps fs.ErrNotExist to ENOENT only, so the check fails regardless of implementation. Effect on a tests-first RED contract: the test can never go GREEN, and a worker asked not to edit tests is forced to stop (correctly) instead of implementing. Fix: assert absence (os.Stat err != nil) or use os.Lstat on the target, never errors.Is(err, fs.ErrNotExist) for a path whose ancestor may be a file. Detected in coding-hermes-tools CHT-016 (internal/fsops TestRootWriteIsAtomic); corrected foreman-direct.", "environment": "", "language": "", "model": "openrouter/deepseek/deepseek-v4.1-flash", "problem_class": "go-fs-errnotexist-enotdir-parent", "provider": "openrouter", "solved_at": "2026-09-17T20:10:08.588Z", "version": ""}Verified and written to ~/go-fs-errnotexist-enotdir-parent.md.
Root cause: When a parent path component is a regular file, stat(2) returns ENOTDIR, not ENOENT. Go's syscall.Errno.Is maps only ENOENT to fs.ErrNotExist:
case oserror.ErrNotExist:
return e == ENOENT // ENOTDIR deliberately excluded
So errors.Is(err, fs.ErrNotExist) is false for such paths — the assertion is logically unsatisfiable, permanently blocking the RED→GREEN contract. os.IsNotExist fails identically (same mapping), and os.Lstat does not help because it still resolves the parent directory and also returns ENOTDIR.
Fix: Assert absence via os.Stat(p); err == nil instead of errors.Is(..., fs.ErrNotExist). If I/O errors must be distinguished, use a helper accepting both ENOENT and ENOTDIR.
Verified empirically (Go 1.26, linux/amd64):
- ancestor-is-file → errors.Is(err, fs.ErrNotExist)=false, ENOTDIR=true
- truly-missing leaf → errors.Is(err, fs.ErrNotExist)=true (control, so the check itself works)
- corrected assertion and isAbsent helper both report absence in both cases
The markdown includes the exact before/after test patch, a production-code helper, a repo-wide detection command (rg), the standalone reproducer, and observed output.
# Evidence - Problem class: go-fs-errnotexist-enotdir-parent - Model: openrouter/deepseek/deepseek-v4.1-flash - Solved: 2026-09-17T20:10:08.588Z - Verification: solution produced by pi in sandbox; see signatures.json
{"description": "In Go, asserting errors.Is(err, fs.ErrNotExist) on os.Stat(path) is unsatisfiable when a PARENT path component is a regular file: the kernel returns ENOTDIR, and syscall.Errno.Is maps fs.ErrNotExist to ENOENT only, so the check fails regardless of implementation. Effect on a tests-first RED contract: the test can never go GREEN, and a worker asked not to edit tests is forced to stop (correctly) instead of implementing. Fix: assert absence (os.Stat err != nil) or use os.Lstat on the target, never errors.Is(err, fs.ErrNotExist) for a path whose ancestor may be a file. Detected in coding-hermes-tools CHT-016 (internal/fsops TestRootWriteIsAtomic); corrected foreman-direct.", "environment": "", "language": "", "model": "openrouter/deepseek/deepseek-v4.1-flash", "problem_class": "go-fs-errnotexist-enotdir-parent", "provider": "openrouter", "solved_at": "2026-09-17T20:10:08.588Z", "version": ""}