{"record":{"id":"613df383bf31cfd2","repo":"mvanhorn/last30days-skill","slug":"engine-s-not-found-on-path-need-python-s-ins","errorCode":null,"errorMessage":"engine: %s not found on PATH (need Python %s+, install from %s; current GOOS=%s)","messagePattern":"engine: (.+?) not found on PATH \\(need Python (.+?)\\+, install from (.+?); current GOOS=(.+?)\\)","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"mcp/internal/engine/run.go","lineNumber":127,"sourceCode":"\t\t\treturn res, fmt.Errorf(\"engine: subprocess exceeded %s timeout\", timeout)\n\t\t}\n\t\treturn res, fmt.Errorf(\"engine: subprocess exited with code %d\", res.ExitCode)\n\t}\n\treturn res, fmt.Errorf(\"engine: subprocess failed to start: %w\", err)\n}\n\n// resolvePython returns an absolute path to the interpreter or an error\n// naming the install URL. If the caller supplied a path we trust it - tests\n// rely on this to inject a stub. Otherwise we look up python3 on PATH.\nfunc resolvePython(override string) (string, error) {\n\tif override != \"\" {\n\t\treturn override, nil\n\t}\n\tpath, err := exec.LookPath(DefaultPythonBinary)\n\tif err == nil {\n\t\treturn path, nil\n\t}\n\treturn \"\", fmt.Errorf(\n\t\t\"engine: %s not found on PATH (need Python %s+, install from %s; current GOOS=%s)\",\n\t\tDefaultPythonBinary, MinPythonVersion, PythonInstallURL, runtime.GOOS,\n\t)\n}\n\nfunc resolveTimeout(explicit time.Duration) time.Duration {\n\tif explicit > 0 {\n\t\treturn explicit\n\t}\n\tif raw := os.Getenv(TimeoutEnvOverride); raw != \"\" {\n\t\tif d, err := time.ParseDuration(raw); err == nil && d > 0 {\n\t\t\treturn d\n\t\t}\n\t\t// Accept bare integer seconds (e.g. \"300\") as documented.\n\t\tif secs, err := strconv.Atoi(raw); err == nil && secs > 0 {\n\t\t\treturn time.Duration(secs) * time.Second\n\t\t}\n\t}","sourceCodeStart":109,"sourceCodeEnd":145,"githubUrl":"https://github.com/mvanhorn/last30days-skill/blob/c7460f6114449ddfe6ea3fc2f23c3d910c0e740c/mcp/internal/engine/run.go#L109-L145","documentation":"Thrown by engine.resolvePython when the MCP server cannot find a 'python3' executable on the process PATH via exec.LookPath. The Go MCP wrapper shells out to python3 to run the embedded last30days.py engine, so a missing interpreter is fatal before any research starts. The message deliberately includes the minimum version (3.12), the install URL, and runtime.GOOS because Windows installs frequently expose only 'python' (or the py launcher), not 'python3'. Note that only the binary name is checked here — the version constraint itself is enforced later by the Python engine, not by this lookup.","triggerScenarios":"Calling engine.Run (directly, or through the MCP 'research'/'preflight' tools) with RunOptions.PythonPath empty while exec.LookPath(\"python3\") fails. Typical concrete cases: running the MCP server on Windows where only python.exe exists; a GUI-launched Claude Desktop whose environment PATH omits Homebrew's /opt/homebrew/bin or ~/.local/bin; a container or sandbox image without Python installed; PATH stripped by a systemd/launchd service.","commonSituations":"Windows hosts (python3.exe rarely exists even when Python is installed — the python.org installer creates python.exe and the py launcher); macOS GUI apps not inheriting shell PATH additions; Docker/distroless images; CI runners where Python is present under a different name or via pyenv shims not activated; MCP clients that spawn the server with a sanitized environment.","solutions":["Install Python 3.12+ from https://www.python.org/downloads/ and ensure its bin directory is on the PATH of the process that launches the MCP server (not just your interactive shell).","On Windows, create a python3 alias: install the python.org build and run 'py -0' to confirm, then either copy/symlink python.exe to python3.exe in the same directory (and put that directory on PATH), or use winget install python.python.3.12 which can expose both names.","For GUI-launched MCP hosts (Claude Desktop), put the interpreter somewhere system-wide (e.g. /usr/local/bin/python3 or C:\\Program Files\\Python312\\) and restart the host so it inherits the updated PATH.","If you embed this package, bypass PATH entirely by setting RunOptions.PythonPath to an absolute interpreter path (resolve it yourself or from an env var you control).","Verify with 'which python3' in the same environment the server runs under, and check 'python3 --version' is >= 3.12."],"exampleFix":"// before: relying on PATH lookup in a GUI-launched host\nres, err := engine.Run(ctx, engine.RunOptions{CacheDir: cacheDir, Args: args})\n// -> \"engine: python3 not found on PATH (need Python 3.12+, ...)\"\n\n// after: resolve an explicit interpreter (env-configurable) and pass it\npythonPath := os.Getenv(\"LAST30DAYS_PYTHON\")\nif pythonPath == \"\" {\n    if p, err := exec.LookPath(\"python3\"); err == nil {\n        pythonPath = p\n    }\n}\nres, err := engine.Run(ctx, engine.RunOptions{\n    PythonPath: pythonPath, // absolute path; empty still falls back to PATH\n    CacheDir:   cacheDir,\n    Args:       args,\n})","handlingStrategy":"validation","validationCode":"// Run before starting the MCP server / first engine.Run call.\nfunc checkInterpreter(override string) error {\n\tif override != \"\" {\n\t\tif _, err := os.Stat(override); err != nil {\n\t\t\treturn fmt.Errorf(\"configured Python path %q not usable: %w\", override, err)\n\t\t}\n\t\treturn nil\n\t}\n\tpath, err := exec.LookPath(\"python3\")\n\tif err != nil {\n\t\treturn fmt.Errorf(\"python3 missing on PATH (GOOS=%s); install Python 3.12+ and restart the host\", runtime.GOOS)\n\t}\n\tout, err := exec.Command(path, \"--version\").Output()\n\tif err != nil || !strings.Contains(string(out), \"Python 3.\") {\n\t\treturn fmt.Errorf(\"interpreter at %s is not Python 3.x: %s\", path, out)\n\t}\n\treturn nil\n}","typeGuard":null,"tryCatchPattern":"// engine.Run returns this as a regular Go error; check it before using the result.\nres, err := engine.Run(ctx, opts)\nif err != nil {\n    if strings.Contains(err.Error(), \"not found on PATH\") {\n        // environment problem: guide user to install Python 3.12+ or set PythonPath\n        return fmt.Errorf(\"setup required: %w\", err)\n    }\n    return err // other engine failures (timeout, non-zero exit) — see res.Stderr for detail\n}","preventionTips":["Smoke-test the deployment environment with 'python3 --version' (expect >= 3.12) using the same launch context as the MCP server (GUI host, service manager, container entrypoint).","Set RunOptions.PythonPath to an absolute interpreter resolved from an env var you control, so behavior does not depend on inherited PATH.","On Windows, ensure a python3 alias exists (python.org installer + PATH, or winget) before deploying the MCP server.","Add a startup preflight: fail fast at server boot with a clear message instead of erroring on the first research call."],"tags":["go","python","environment","path","mcp","setup"],"backgroundTag":null,"analyzedSha":"c7460f6114449ddfe6ea3fc2f23c3d910c0e740c","analyzedAt":"2026-08-15T03:34:49.540Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}