anomalyco/sst · error
failed to read workspace directory
Error message
failed to read workspace directory: %w
What it means
After copying handler directories, copySourceFilesSimple lists the workspace directory with os.ReadDir to copy root-level .py files into the build output. This error is returned when the workspace directory itself cannot be read. It wraps the OS error (ENOENT, EACCES, ENOTDIR).
Solutions
- Verify the pyproject.toml / workspace root path exists: `ls <projectRoot>/pyproject.toml`; fix config or restore the directory.
- Run `sst deploy` from the app root so projectInfo paths resolve correctly.
- Check permissions on the workspace directory (`chmod u+rx <workspaceDir>`).
- Clean and regenerate build state: `rm -rf .sst` and redeploy.
Example fix
// before Error: failed to copy source files: failed to read workspace directory: open /app/packages/api: no such file or directory // after $ cd /app && ls packages/api/pyproject.toml # fix path or restore dir $ sst deploy
Defensive patterns
Strategy: validation
Validate before calling
const wsDir = path.dirname(pyprojectPath); // what SST derives
if (!fs.existsSync(wsDir)) throw new Error(`workspace dir ${wsDir} missing — check pyproject.toml location`);
fs.accessSync(wsDir, fs.constants.R_OK | fs.constants.X_OK); Type guard
null
Try / catch
try {
await deploy();
} catch (e) {
if (/failed to read workspace directory/.test(e.message)) {
console.error('Workspace root missing/unreadable — verify pyproject.toml path and run from app root');
throw e;
} else throw e;
} Prevention
- Keep pyproject.toml in place; don't rename its directory without updating config
- Always run sst from the app/project root
- Avoid symlinking the workspace to volatile locations
- Verify SourceRoot paths after project restructuring
When it happens
Trigger: os.ReadDir(workspaceDir) fails when projectInfo.SourceRoot / the directory containing pyproject.toml does not exist, was deleted, or is not readable — e.g. a misconfigured pyproject path or a workspace root that is actually a file.
Common situations: pyproject.toml moved/renamed so the derived workspace dir no longer exists; running deploy from the wrong working directory; project root renamed without updating config; symlinked workspace pointing to a deleted location.
Related errors
- failed to copy dependencies to artifact
- failed to copy directory
- failed to copy file
- failed to copy to
- failed to copy source files
AI-assisted analysis of anomalyco/sst@a0bd20f762 (2026-08-30).
Data as JSON: /api/errors/60f7be45b59e31fa.
Report an issue: GitHub.
Appendix: source
Thrown at pkg/runtime/python/build.go:782
candidate := parts[i]
candidatePath := filepath.Join(workspaceDir, candidate)
if info, err := os.Stat(candidatePath); err == nil && info.IsDir() {
if err := copyDir(candidatePath, filepath.Join(outputBase, candidate), skipContent); err != nil {
return fmt.Errorf("failed to copy directory %s: %w", candidate, err)
}
copied = true
break
}
}
if !copied {
// Handler path fully resolved by workspaceDir — root .py files will be copied below
}
}
// Also copy root-level .py files
entries, err := os.ReadDir(workspaceDir)
if err != nil {
return fmt.Errorf("failed to read workspace directory: %w", err)
}
for _, entry := range entries {
if !entry.IsDir() && strings.HasSuffix(entry.Name(), ".py") {
if err := copyFile(filepath.Join(workspaceDir, entry.Name()), filepath.Join(outputBase, entry.Name())); err != nil {
return fmt.Errorf("failed to copy file %s: %w", entry.Name(), err)
}
}
}
return nil
}
// copySyncedDependencies installs dependencies with correct platform targeting
func copySyncedDependencies(ctx context.Context, input *runtime.BuildInput, projectInfo *projectInfo, architecture string) error {
requirementsPath := filepath.Join(input.Out(), "requirements.txt")
if _, err := os.Stat(requirementsPath); os.IsNotExist(err) {
slog.Warn("requirements.txt not found, skipping dependency installation", "path", requirementsPath)View on GitHub (pinned to a0bd20f762)