anomalyco/sst · error

%s

Error message

%s

What it means

detailedExportError wraps a failed `uv export`/`uv lock` invocation run during the Python build (via runUvExport) with the raw stderr plus, when the stderr matches known patterns, a heuristic suggestion. The `%s` formatting simply re-wraps the accumulated message as a single error. It exists because uv failures during dependency export are the most common cause of Python build breakage and the raw uv output alone is often cryptic.

Source

Thrown at pkg/runtime/python/build.go:1550

	if cmd.PackageName != "" {
		errorMsg += fmt.Sprintf(" (exporting package: %s)", cmd.PackageName)
	}
	if cmd.OutputFile != "" {
		errorMsg += fmt.Sprintf(" to file: %s", cmd.OutputFile)
	}
	errorMsg += fmt.Sprintf(" in workspace: %s", cmd.WorkspaceDir)

	if result.Stderr != "" {
		errorMsg += fmt.Sprintf("\nError output: %s", result.Stderr)
	}

	if strings.Contains(result.Stderr, "package") && strings.Contains(result.Stderr, "not found") {
		errorMsg += "\nSuggestion: Check if the package name is correct and exists in the workspace"
	} else if strings.Contains(result.Stderr, "lock") {
		errorMsg += "\nSuggestion: Run 'uv sync' first to ensure dependencies are resolved"
	}

	return fmt.Errorf("%s", errorMsg)
}

// runUvCommand executes a command with timeout and progress logging
func runUvCommand(ctx context.Context, command string, args []string, workingDir string) (*commandResult, error) {
	startTime := time.Now()

	cmdCtx, cancel := context.WithTimeout(ctx, uvCommandTimeout)
	defer cancel()

	cmd := process.CommandContext(cmdCtx, command, args...)
	if workingDir != "" {
		cmd.Dir = workingDir
	}
	cmd.Env = os.Environ()

	done := make(chan bool)
	go func() {
		ticker := time.NewTicker(30 * time.Second)

View on GitHub (pinned to a0bd20f762)

Solutions

  1. Run `uv sync` (or `uv lock`) in the project root to regenerate/refresh uv.lock, then redeploy.
  2. Check stderr in the wrapped message: if it mentions 'package ... not found', verify the package name in pyproject.toml [tool.uv.sources] / dependencies and confirm the workspace member path exists.
  3. Commit uv.lock to version control so CI builds see resolved dependencies.
  4. Run the same uv command manually in the project directory to see the full error output.

Example fix

// before (missing lock file)
// sst deploy -> failed: uv export: lock file not found

// after (shell, in the function's project dir)
// uv sync && sst deploy
Defensive patterns

Strategy: try-catch

Validate before calling

// shell, before deploy
cd <project-root> && test -f uv.lock || (echo 'uv.lock missing; run uv sync' && uv sync)

Try / catch

// wrap deploy and inspect suggestion
catch (e) {
  if (String(e).includes("Suggestion: Run 'uv sync'")) await $`uv sync`;
  else if (String(e).includes("package") && String(e).includes("not found")) fixPackageNameInPyproject();
  throw e;
}

Prevention

When it happens

Trigger: A `uv export` (or related uv command) exits non-zero: the package referenced in pyproject.toml/requirements is misspelled or absent from the workspace/index, or the uv.lock file is missing/stale so the export cannot resolve locked dependencies.

Common situations: Adding a new internal workspace member without running `uv sync` to regenerate uv.lock; typos in a package name; a workspace source path pointing to a package that no longer exists; running builds in CI on a fresh checkout where uv.lock was never committed.

Related errors


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