{"record":{"id":"909bf4aaf9554ccb","repo":"anomalyco/sst","slug":"failed-to-copy-pyproject-toml-for-workspace-packag","errorCode":null,"errorMessage":"failed to copy pyproject.toml for workspace package %s: %w","messagePattern":"failed to copy pyproject\\.toml for workspace package (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/runtime/python/build.go","lineNumber":707,"sourceCode":"\t\tif _, err := os.Stat(fullPath); err != nil {\n\t\t\tslog.Warn(\"workspace package directory not found\", \"path\", fullPath, \"line\", line)\n\t\t\tcontinue\n\t\t}\n\n\t\t// Copy to artifact at the same relative path\n\t\tdestPath := filepath.Join(input.Out(), pkgPath)\n\t\tif _, err := os.Stat(destPath); err == nil {\n\t\t\t// Already exists — just ensure pyproject.toml is present for uv pip install\n\t\t\tsrcPyproject := filepath.Join(fullPath, \"pyproject.toml\")\n\t\t\tdestPyproject := filepath.Join(destPath, \"pyproject.toml\")\n\t\t\tif _, err := os.Stat(srcPyproject); err == nil {\n\t\t\t\tif _, err := os.Stat(destPyproject); err != nil {\n\t\t\t\t\tdata, readErr := os.ReadFile(srcPyproject)\n\t\t\t\t\tif readErr != nil {\n\t\t\t\t\t\treturn fmt.Errorf(\"failed to read pyproject.toml for workspace package %s: %w\", pkgPath, readErr)\n\t\t\t\t\t}\n\t\t\t\t\tif err := os.WriteFile(destPyproject, data, 0644); err != nil {\n\t\t\t\t\t\treturn fmt.Errorf(\"failed to copy pyproject.toml for workspace package %s: %w\", pkgPath, err)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\n\t\tif err := os.MkdirAll(filepath.Dir(destPath), 0755); err != nil {\n\t\t\treturn fmt.Errorf(\"failed to create directory for workspace package %s: %w\", pkgPath, err)\n\t\t}\n\n\t\t// Preserve pyproject.toml and metadata for uv pip install\n\t\tif err := copyDir(fullPath, destPath, skipBuildArtifacts); err != nil {\n\t\t\treturn fmt.Errorf(\"failed to copy workspace package %s: %w\", pkgPath, err)\n\t\t}\n\n\t}\n\n\treturn nil","sourceCodeStart":689,"sourceCodeEnd":725,"githubUrl":"https://github.com/anomalyco/sst/blob/a0bd20f762883e72a35caccb4896c42ce5b3f707/pkg/runtime/python/build.go#L689-L725","documentation":"During a container build of a Python function, SST copies each workspace package referenced by a relative path in requirements.txt into the build output. When the package directory already exists in the output but is missing its pyproject.toml, SST reads the source pyproject.toml and writes it into the destination; this error is returned when that os.WriteFile fails. It wraps the underlying OS error (permissions, disk full, destination being a directory, etc.).","triggerScenarios":"os.WriteFile(destPyproject, data, 0644) fails inside copyWorkspacePackagesForContainer (input.IsContainer=true) when: the destination path destPath/pyproject.toml exists as a directory, the build output directory is read-only, or the disk is full/exceeds quota.","commonSituations":"Build output (.sst directory) left with stale artifacts owned by root from a Docker run; disk quota exceeded on CI runners; a directory literally named pyproject.toml accidentally committed inside the workspace package; output volume mounted read-only.","solutions":["Check the wrapped error: run `ls -la` on the destPath/pyproject.toml inside the .sst output — if it is a directory or root-owned, delete the stale .sst build directory and redeploy.","Free disk space or raise the quota if the wrapped error is ENOSPC.","Ensure the build output location is writable by the user running `sst deploy` (fix ownership: `sudo chown -R $USER .sst`).","If a folder named pyproject.toml exists in the package, rename/remove it."],"exampleFix":"// before\n$ sst deploy\nError: failed to copy pyproject.toml for workspace package ./packages/core: open /path/.sst/.../pyproject.toml: permission denied\n// after\n$ rm -rf .sst\n$ sudo chown -R $USER . # or free disk space\n$ sst deploy","handlingStrategy":"validation","validationCode":"const dest = path.join(buildOut, pkgPath, 'pyproject.toml');\nif (fs.existsSync(dest) && fs.statSync(dest).isDirectory()) throw new Error(`destination ${dest} is a directory; clean .sst and redeploy`);\nfs.accessSync(path.dirname(dest), fs.constants.W_OK);","typeGuard":"function isWritableFileDest(p) { try { const s = fs.statSync(p); return !s.isDirectory(); } catch { return true; } }","tryCatchPattern":"try {\n  await deploy();\n} catch (e) {\n  if (/failed to copy pyproject.toml for workspace package/.test(e.message)) {\n    fs.rmSync('.sst', { recursive: true, force: true });\n    await deploy(); // retry after cleaning stale output\n  } else throw e;\n}","preventionTips":["Don't run deploys with sudo or mixed users; keep one owning user for .sst","Never name a file/dir `pyproject.toml` inside package source other than the manifest","Monitor disk space on CI runners before deploy","Clean .sst after interrupted Docker-based builds"],"tags":["filesystem","python","container-build","permissions"],"backgroundTag":"file-write-permission-denied","analyzedSha":"a0bd20f762883e72a35caccb4896c42ce5b3f707","analyzedAt":"2026-08-30T11:26:00.383Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}