pulumi/pulumi · error
opening %s: %w
Error message
opening %s: %w
What it means
When appending a minimal [project] section to an existing pyproject.toml, os.OpenFile with O_APPEND|O_WRONLY failed. This typically means the file cannot be opened for writing, e.g. it does not actually exist, is read-only, or permissions block writes.
Source
Thrown at sdk/python/toolchain/uv.go:198
}
// pyproject.toml exists but has no [project]. If requirements.txt sits next to it, append a minimal
// [project] section and merge the deps in.
requirementsTxt := filepath.Join(existingPyprojectDir, "requirements.txt")
if _, statErr := os.Stat(requirementsTxt); statErr != nil {
if errors.Is(statErr, os.ErrNotExist) {
return nil
}
return fmt.Errorf("error while looking for requirements.txt: %w", statErr)
}
name := projectName
if name == "" {
name = filepath.Base(existingPyprojectDir)
}
pyprojectPath := filepath.Join(existingPyprojectDir, "pyproject.toml")
section := fmt.Sprintf("\n[project]\nname = %q\nversion = \"0.1.0\"\ndependencies = []\n", name)
f, err := os.OpenFile(pyprojectPath, os.O_APPEND|os.O_WRONLY, 0)
if err != nil {
return fmt.Errorf("opening %s: %w", pyprojectPath, err)
}
if _, err := f.WriteString(section); err != nil {
contract.IgnoreClose(f)
return fmt.Errorf("appending [project] to %s: %w", pyprojectPath, err)
}
if err := f.Close(); err != nil {
return fmt.Errorf("closing %s: %w", pyprojectPath, err)
}
return u.mergeRequirementsTxt(ctx, existingPyprojectDir, showOutput, infoWriter, errorWriter)
}
requirementsTxtDir, err := searchup(cwd, "requirements.txt")
pyprojectTomlDir := cwd
hasRequirementsTxt := false
if err == nil {
pyprojectTomlDir = requirementsTxtDir
hasRequirementsTxt = true
} else if !errors.Is(err, os.ErrNotExist) {View on GitHub (pinned to 793f7b2e16)
Solutions
- Make pyproject.toml writable: chmod u+w <path>/pyproject.toml
- Run pulumi as the user who owns the project directory
- Manually add a [project] section (name, version, dependencies) to pyproject.toml so the append path is skipped
- Ensure the file exists and is a regular file, not a directory or dangling symlink
Example fix
// before -r--r--r-- pyproject.toml // after $ chmod u+w pyproject.toml
Defensive patterns
Strategy: validation
Validate before calling
import os
path = "pyproject.toml"
assert os.path.isfile(path), f"{path} missing or not a file"
assert os.access(path, os.W_OK), f"{path} not writable: run chmod u+w {path}" Try / catch
try {
await runPulumi();
} catch (e) {
if (String(e).includes("opening ") && String(e).includes("pyproject.toml")) {
console.error("pyproject.toml not writable; fix file mode or run as file owner");
}
throw e;
} Prevention
- Do not commit pyproject.toml with read-only modes (444)
- Run pulumi as the same user that owns the project files
- Add a [project] section manually so the append step never runs
- Avoid read-only container filesystems for project directories
When it happens
Trigger: PrepareProject found a pyproject.toml without a [project] section and a requirements.txt next to it, then failed to open that pyproject.toml for appending (EACCES on read-only file, file deleted between searchup and open, EISDIR).
Common situations: pyproject.toml checked into git as read-only or with 444 permissions; running pulumi as a different user than the file owner; read-only container filesystem; build system resetting file mode.
Related errors
- error while looking for uv.lock in %s: %w
- error while looking for pyproject.toml in %s: %w
- error while looking for nearest pyproject.toml in %s: %w
- error while looking for requirements.txt: %w
- appending [project] to %s: %w
AI-assisted analysis of pulumi/pulumi@793f7b2e16 (2026-08-31).
Data as JSON: /api/errors/c3465a0384a91baf.
Report an issue: GitHub.