{"record":{"id":"0bcbfdf62d8180a9","repo":"anomalyco/sst","slug":"failed-to-copy-directory-s-w","errorCode":null,"errorMessage":"failed to copy directory %s: %w","messagePattern":"failed to copy directory (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/runtime/python/build.go","lineNumber":768,"sourceCode":"\t}\n\n\toutputBase := input.Out()\n\t// For container builds, source files go at root of build context (Dockerfile expects it).\n\t// For zip builds, preserve the nested directory structure via outputPrefix.\n\tif outputPrefix != \"\" && !input.IsContainer {\n\t\toutputBase = filepath.Join(input.Out(), outputPrefix)\n\t}\n\n\tif strings.Contains(handlerPath, \"/\") {\n\t\t// Find the top-level directory that exists in the workspace\n\t\tparts := strings.Split(handlerPath, \"/\")\n\t\tcopied := false\n\t\tfor i := 0; i < len(parts)-1; i++ {\n\t\t\tcandidate := parts[i]\n\t\t\tcandidatePath := filepath.Join(workspaceDir, candidate)\n\t\t\tif info, err := os.Stat(candidatePath); err == nil && info.IsDir() {\n\t\t\t\tif err := copyDir(candidatePath, filepath.Join(outputBase, candidate), skipContent); err != nil {\n\t\t\t\t\treturn fmt.Errorf(\"failed to copy directory %s: %w\", candidate, err)\n\t\t\t\t}\n\t\t\t\tcopied = true\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\tif !copied {\n\t\t\t// Handler path fully resolved by workspaceDir — root .py files will be copied below\n\t\t}\n\t}\n\n\t// Also copy root-level .py files\n\tentries, err := os.ReadDir(workspaceDir)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to read workspace directory: %w\", err)\n\t}\n\tfor _, entry := range entries {\n\t\tif !entry.IsDir() && strings.HasSuffix(entry.Name(), \".py\") {\n\t\t\tif err := copyFile(filepath.Join(workspaceDir, entry.Name()), filepath.Join(outputBase, entry.Name())); err != nil {","sourceCodeStart":750,"sourceCodeEnd":786,"githubUrl":"https://github.com/anomalyco/sst/blob/a0bd20f762883e72a35caccb4896c42ce5b3f707/pkg/runtime/python/build.go#L750-L786","documentation":"copySourceFilesSimple locates the top-level source directory of the handler (e.g. `services/api/functions/handler.ts` → first path component that exists as a dir in the workspace) and recursively copies it into the build output. This error is returned when that copyDir fails. It wraps the underlying OS error from copying a file inside that directory.","triggerScenarios":"copyDir(candidatePath, filepath.Join(outputBase, candidate), skipContent) fails in copySourceFilesSimple — a source file disappears mid-copy, a file is unreadable (permissions), or the destination cannot be written.","commonSituations":"Handler source directory contains files owned by another user; a file is removed by a code generator/watcher during deploy; read-only source mount; output directory full.","solutions":["Check the wrapped error for the failing filename; restore permissions (`chmod -R u+r <dir>`) or recreate the missing file.","Stop concurrent watchers/generators, then rerun the deploy.","Clean the build output (`rm -rf .sst`) and redeploy to clear conflicting destinations.","Verify free disk space on the volume holding the build output."],"exampleFix":"// before\nError: failed to copy source files: failed to copy directory functions: open functions/handler.py: permission denied\n// after\n$ chmod -R u+r functions/\n$ sst deploy","handlingStrategy":"try-catch","validationCode":"fs.accessSync(handlerDir, fs.constants.R_OK);\nfs.accessSync(buildOut, fs.constants.W_OK);","typeGuard":"null","tryCatchPattern":"try {\n  await deploy();\n} catch (e) {\n  if (/failed to copy directory/.test(e.message)) {\n    const m = e.message.match(/failed to copy directory (\\S+): (.*)/);\n    console.error(`Fix perms/missing file in ${m?.[1]}: ${m?.[2]}`);\n    throw e;\n  } else throw e;\n}","preventionTips":["chmod -R u+r source dirs before CI deploys","Pause file watchers/generators during deploy","Clean .sst when build output layout changes","Keep source tree free of unreadable or root-owned files"],"tags":["filesystem","python","build","copy"],"backgroundTag":"file-copy-failed","analyzedSha":"a0bd20f762883e72a35caccb4896c42ce5b3f707","analyzedAt":"2026-08-30T11:26:00.383Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}