anomalyco/sst · error

failed to scan artifact files: %v

Error message

failed to scan artifact files: %v

What it means

Raised in syncPythonFiles (pkg/runtime/python/python.go:309) when filepath.Walk over the artifact output directory (input.Build.Out) fails while collecting existing .py artifact files. Only runs when the dest dir exists. Indicates the artifact directory became unreadable or changed (deleted files, permission loss) during the sync.

Source

Thrown at pkg/runtime/python/python.go:309

	if _, err := os.Stat(destDir); err == nil {
		err = filepath.Walk(destDir, func(path string, info os.FileInfo, err error) error {
			if err != nil {
				return err
			}

			relPath, err := filepath.Rel(destDir, path)
			if err != nil {
				return err
			}

			if !info.IsDir() && strings.HasSuffix(path, ".py") {
				artifactFiles[relPath] = info
			}

			return nil
		})
		if err != nil {
			return fmt.Errorf("failed to scan artifact files: %v", err)
		}
	}

	// Delete files in artifacts that no longer exist in source
	for relPath := range artifactFiles {
		if _, exists := sourceFiles[relPath]; !exists {
			artifactPath := filepath.Join(destDir, relPath)
			if err := os.Remove(artifactPath); err != nil {
				return fmt.Errorf("failed to delete %s: %v", artifactPath, err)
			}
		}
	}

	// Copy/update changed files
	for relPath, sourceInfo := range sourceFiles {
		sourcePath := filepath.Join(srcDir, relPath)
		artifactPath := filepath.Join(destDir, relPath)

View on GitHub (pinned to a0bd20f762)

Solutions

  1. Check the wrapped error path and fix permissions: chmod -R u+rX <path>
  2. Stop other sst processes, delete the function's artifact directory, and let `sst dev`/`sst deploy` rebuild it fresh
  3. If recurring in CI, run builds in isolated workspaces so concurrent runs don't share .sst artifacts

Example fix

// before
sst dev -> failed to scan artifact files: open .sst/artifacts/... : permission denied
// after
rm -rf .sst/artifacts/<function-dir>
sst dev
Defensive patterns

Strategy: validation

Validate before calling

// check artifact dir is usable before sync
if info, err := os.Stat(artifactDir); err == nil {
    if !info.IsDir() { return fmt.Errorf("artifact path is not a directory: %s", artifactDir) }
    if f, err := os.Open(artifactDir); err != nil { return fmt.Errorf("artifact dir unreadable: %v", err) } else { f.Close() }
}

Try / catch

if err := syncPythonFiles(src, dst); err != nil {
    if strings.Contains(err.Error(), "failed to scan artifact files") {
        os.RemoveAll(dst) // nuke corrupt artifacts, rebuild clean
        return syncPythonFiles(src, dst)
    }
    return err
}

Prevention

When it happens

Trigger: Artifact dir (.sst artifacts for the function) with read-restricted subdirectories; files deleted mid-walk by a concurrent build; a corrupt or partially-written artifact directory from an interrupted deploy.

Common situations: Two sst processes sharing one project writing artifacts simultaneously; artifacts directory synced/restored with wrong permissions; interrupted `sst deploy` leaving broken dirs in legacy workspace-layout Python projects.

Understand the failure class

Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.

Related errors


AI-assisted analysis of anomalyco/sst@a0bd20f762 (2026-08-30). Data as JSON: /api/errors/999c3f8dda95f2e6. Report an issue: GitHub.