anomalyco/sst · error

Handler not found: %v

Error message

Handler not found: %v

What it means

PythonRuntime.Build calls resolveHandler to validate the configured handler before building, and wraps ANY resolveHandler failure (missing file, path errors) into the generic "Handler not found: %v". Note it uses %v on the handler string rather than %w, so the underlying cause is discarded — the handler value is echoed to help locate the config problem.

Source

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

	}

	// Clear deps cache once per SST run
	globalDepsCacheClearOnce.Do(func() {
		artifactsDir := filepath.Dir(input.Out())
		depsDir := filepath.Join(artifactsDir, ".deps")
		if _, err := os.Stat(depsDir); err == nil {
			if err := os.RemoveAll(depsDir); err != nil {
				slog.Warn("failed to clear deps cache", "error", err)
			}
		}
	})

	r.concurrency.Acquire(ctx, 1)
	defer r.concurrency.Release(1)

	_, err := resolveHandler(path.ResolveRootDir(input.CfgPath), input.Handler)
	if err != nil {
		return nil, fmt.Errorf("Handler not found: %v", input.Handler)
	}

	result, err := r.CreateBuildAsset(ctx, input)
	if err != nil {
		return nil, err
	}

	return result, nil
}

func (r *PythonRuntime) Match(runtime string) bool {
	return strings.HasPrefix(runtime, "python")
}

// ShouldRunEagerly returns false to enable lazy worker startup.
// Python lacks static import analysis, so any file change triggers ShouldRebuild()
// for ALL functions. Lazy startup avoids a startup storm of 50+ processes.
func (r *PythonRuntime) ShouldRunEagerly() bool {

View on GitHub (pinned to a0bd20f762)

Solutions

  1. Confirm the handler value matches an existing file: e.g. handler "src/index.handler" requires <root>/src/index.py.
  2. Check for typos and case sensitivity in the handler path (Linux is case-sensitive).
  3. Verify the function's cfgPath/sst root points at the directory containing your Python code.
  4. Temporarily run the underlying resolution by attempting a local python import of the same module path to sanity-check the path.

Example fix

// before (sst.config.ts)
handler: "src/index.handelr"

// after
handler: "src/index.handler"
Defensive patterns

Strategy: validation

Validate before calling

// node/bun: verify handler maps to a real .py file before Build
import { statSync } from "node:fs";
import path from "node:path";
const file = "src/index"; // derived from handler "src/index.handler"
const candidates = [file + ".py",
  ...["src","app","functions","lambda","handlers","lib"].map(d => path.join(d, file + ".py"))];
if (!candidates.some(c => { try { return statSync(path.join(root, c)).isFile(); } catch { return false; } }))
  throw new Error(`Handler target missing: ${file}.py`);

Try / catch

try { await deploy() } catch (e) {
  if (String(e).startsWith("Handler not found:"))
    console.error("Check handler in config:", String(e));
  throw e;
}

Prevention

When it happens

Trigger: Build was invoked with input.Handler pointing to a non-existent Python file relative to ResolveRootDir(input.CfgPath) — e.g. typo, wrong relative path, or the handler module was renamed/deleted.

Common situations: Refactoring renamed index.py to main.py without updating sst.config.ts; handler path written with a leading slash or './'; deploying from a different working directory so the root dir resolves elsewhere; case mismatch on Linux (Handler.py vs handler.py).

Related errors


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