golang/go · error
%s exists but is writable
Error message
%s exists but is writable
What it means
Thrown by the exists command (with -readonly flag) in the Go test script framework when a file exists but has any write permission bit set (mode & 0o222 != 0). The command asserts that files should be read-only; if any of owner/group/other write bits are set, it fails.
Source
Thrown at src/cmd/internal/script/cmds.go:614
case "-exec":
exec = true
args = args[1:]
default:
break loop
}
}
if len(args) == 0 {
return nil, ErrUsage
}
for _, file := range args {
file = s.Path(file)
info, err := os.Stat(file)
if err != nil {
return nil, err
}
if readonly && info.Mode()&0222 != 0 {
return nil, fmt.Errorf("%s exists but is writable", file)
}
if exec && runtime.GOOS != "windows" && info.Mode()&0111 == 0 {
return nil, fmt.Errorf("%s exists but is not executable", file)
}
}
return nil, nil
})
}
// Grep checks that file content matches a regexp.
// Like stdout/stderr and unlike Unix grep, it accepts Go regexp syntax.
//
// Grep does not modify the State's stdout or stderr buffers.
// (Its output goes to the script log, not stdout.)
func Grep() Cmd {
return Command(
CmdUsage{View on GitHub (pinned to b6b368adc5)
Solutions
- Run `chmod 0444 file` or `chmod 0555 file` in the script before the exists -readonly check.
- Verify that the file creation step is followed by an explicit chmod to remove write bits.
- Check that no prior step re-adds write permissions after the chmod.
Example fix
// Before: // exists -readonly file.txt // // After (add chmod first): // chmod 0444 file.txt // exists -readonly file.txt
Defensive patterns
Strategy: validation
Validate before calling
// Ensure file is read-only before asserting exists -readonly:
// In the test script:
// chmod 0444 file.txt
// exists -readonly file.txt
// Programmatic check:
func ensureReadOnly(path string) error {
info, err := os.Stat(path)
if err != nil { return err }
if info.Mode() & 0222 != 0 {
return os.Chmod(path, info.Mode() & ^fs.FileMode(0222))
}
return nil
} Prevention
- Always chmod files to remove write bits before exists -readonly assertions.
- Use 0444 for files or 0555 for directories/executables in test scripts.
- Verify that no prior step re-adds write permissions.
When it happens
Trigger: exists -readonly <file> is called and os.Stat returns a mode where any of the three write bits (0o200, 0o020, 0o002) is set. The check is `info.Mode()&0222 != 0`.
Common situations: Test script creates a file (which typically defaults to writable via 0o644 or umask) then asserts it should be read-only. The file was not chmod'd to remove write bits before the assertion. Also occurs when a test expects a file to be locked/immutable but the filesystem or OS enforces different permissions.
Related errors
- %s exists but is not executable
- %s and %s differ
- found %d matches for %#q in %s
- no match for %#q in %s
- ErrUnexpectedSuccess
AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12).
Data as JSON: /api/errors/405667a356de587a.
Report an issue: GitHub.