QGIS Processing "Algorithm Not Found" Error in Python: How to Fix It
On this page
Problem statement
The algorithm is right there in the Processing Toolbox. From Python it does not exist:
QgsProcessingException: Error: Algorithm native:buffer not found
Or it exists on your laptop and not on the server:
QgsProcessingException: Error: Algorithm native:selectbyexpression not found
Or the id resolves and the call fails on its input instead:
QgsProcessingException: Unable to execute algorithm
Could not load source layer for INPUT: nope.gpkg not found
Every message on this page was produced by running the code below, on QGIS 4.2 and on the 3.44 LTR in the official qgis/qgis:ltr image, with Rutland's schools as the data. There are only three ways to get the first two: the registry was never populated, the provider that owns the algorithm is not in this installation, or the id you used is not an id this QGIS knows. The error text is the same for all three, which is why it feels mysterious.
The registry comes up empty, or without your id, when:
Processing.initialize()was never called in a standalone scriptProcessing.initialize()ran beforeQgsApplication.initQgis()- the id is newer than the QGIS running it β 29
native:ids in QGIS 4.2 do not exist in 3.44 - the id was typed from the dialog title rather than copied from the History panel
- the algorithm belongs to a provider that is not installed where the script runs (PDAL in the 3.44 image, a plugin provider such as SAGA NextGen)
- the script imports
processingfrom a different QGIS installation than the one it initialised
Quick answer
To fix "algorithm not found":
- initialise QGIS then Processing, in that order, in every standalone script
- ask the registry whether the id exists before blaming the call
- copy ids from the Processing History panel β on the QGIS version the script will run on
- check
algorithmHelp()for the parameter names β they are not the dialog labels
import os
import sys
os.environ.setdefault("QT_QPA_PLATFORM", "offscreen")
from qgis.core import QgsApplication
qgs = QgsApplication([], False)
qgs.initQgis() # 1. application first
sys.path.append("/usr/share/qgis/python/plugins")
from processing.core.Processing import Processing
import processing
Processing.initialize() # 2. then the registry
reg = QgsApplication.processingRegistry()
print("native:buffer ->", reg.algorithmById("native:buffer")) # 3. verify the id exists
result = processing.run("native:buffer", {
"INPUT": "data/schools.gpkg|layername=schools",
"DISTANCE": 50,
"OUTPUT": "out/buffered.gpkg",
})
print(result["OUTPUT"])
qgs.exitQgis()
algorithmById() returning None proves the problem is registration or the id itself, and separates that from a parameter problem in one line.
The anatomy of an algorithm id
provider:name β and the provider half is where most failures live.Initialise in order, list the registry, copy the right id
Processing.initialize() runs β and that must come after initQgis().Initialise Processing in the right order
Inside QGIS, the Toolbox has already done this. Standalone, nothing has: after initQgis() alone, the registry holds no providers and no algorithms.
import os, sys
os.environ.setdefault("QT_QPA_PLATFORM", "offscreen")
from qgis.core import QgsApplication
qgs = QgsApplication([], False)
qgs.initQgis() # providers, CRS db, expression functions
sys.path.append("/usr/share/qgis/python/plugins") # where the `processing` package lives
from processing.core.Processing import Processing
Processing.initialize() # registers native:, qgis:, gdal:, grass:, 3d: β¦
Calling Processing.initialize() before the application exists does not raise. It prints Application path not initialized dozens of times, returns, and leaves nothing behind: native:buffer is still not found after initQgis() (example 1).
If import processing itself fails with ModuleNotFoundError, the plugins path is wrong for your installation β it is /usr/share/qgis/python/plugins on Debian, Ubuntu and the official Docker image, and Contents/Resources/python/plugins inside a macOS bundle.
List what is actually registered
Once the registry is populated, ask it rather than guessing.
reg = QgsApplication.processingRegistry()
print("providers:", [p.id() for p in reg.providers()])
print("algorithms:", len(reg.algorithms()))
# find every algorithm whose id or name mentions "buffer"
for alg in reg.algorithms():
if "buffer" in alg.id().lower() or "buffer" in alg.displayName().lower():
print(f"{alg.id():32} {alg.displayName()}")
providers: ['3d', 'gdal', 'grass', 'model', 'native', 'pdal', 'project', 'qgis', 'script']
algorithms: 772
gdal:buffervectors Buffer vectors
gdal:onesidebuffer One side buffer
grass:r.buffer r.buffer
grass:r.buffer.lowmem r.buffer.lowmem
grass:v.buffer v.buffer
native:buffer Buffer
native:bufferbym Variable width buffer (by M value)
native:multiringconstantbuffer Multi-ring buffer (constant distance)
native:singlesidedbuffer Single sided buffer
native:taperedbuffer Tapered buffers
native:wedgebuffers Create wedge buffers
qgis:variabledistancebuffer Variable distance buffer
An empty provider list means Processing.initialize() did not run, or ran too early. A populated list without your algorithm means the id is wrong for this version or its provider is not installed.
Copy the id from the History panel, not the dialog
Run the algorithm once in the QGIS GUI, then open Processing β History. Every run is recorded as the exact Python call the dialog made:
processing.run("native:joinattributesbylocation", {
'INPUT': '/data/points.gpkg|layername=points',
'JOIN': '/data/zones.gpkg|layername=zones',
'PREDICATE': [0],
'JOIN_FIELDS': [],
'METHOD': 0,
'DISCARD_NONMATCHING': False,
'PREFIX': '',
'OUTPUT': 'TEMPORARY_OUTPUT',
})
That is the ground truth for the QGIS that wrote it: correct id, correct parameter names, correct enum values. Guessing an id from the dialog title ("Join attributes by location") is how you end up with qgis:joinattributes, which does not exist in either version. The catch is the version: a History entry from QGIS 4.2 can name an algorithm that the 3.44 LTR on your server has under a different prefix, or not at all.
Know the provider prefixes β and which direction ids move
| Prefix | Provider | Registered by Processing.initialize() in the two builds tested |
|---|---|---|
native: |
QGIS C++ algorithms | 321 in 3.44, 350 in 4.2 |
qgis: |
Python algorithms | 44 in 3.44, 31 in 4.2 β 13 moved to native: |
gdal: |
GDAL/OGR command-line tools | 57 and 59; runs ogr2ogr, gdalwarp and friends |
grass: |
GRASS GIS | 307 in both, because GRASS was installed in both |
pdal: |
PDAL point clouds | 24 in 4.2, absent from the 3.44 image |
3d:, model:, script: |
3D, models and scripts from the profile | model and script empty in a fresh profile |
The move from qgis: to native: is the one that bites, and in one direction only. The 13 algorithms that 4.2 ported to C++ β selectbyexpression, randomselection, minimumboundinggeometry, heatmapkerneldensityestimation and nine more β still resolve under their old qgis: ids in 4.2, which quietly redirects them. Their new native: ids do not exist in 3.44 at all. Code written against the older release keeps working on the newer one; code copied from the newer one fails on the older.
Read the parameter names from the algorithm itself
An id that resolves but rejects your parameters is a different problem with a one-line diagnosis.
processing.algorithmHelp("native:buffer")
This prints every parameter, its type, whether it is optional, and the integer values behind each enum β the information the dialog hides behind friendly labels. The same comes from the definitions directly:
alg = QgsApplication.processingRegistry().algorithmById("native:buffer")
for name in ("END_CAP_STYLE", "JOIN_STYLE"):
param = alg.parameterDefinition(name)
print(name, dict(enumerate(param.options())), "default", param.defaultValue())
END_CAP_STYLE {0: 'Round', 1: 'Flat', 2: 'Square'} default 0
JOIN_STYLE {0: 'Round', 1: 'Miter', 2: 'Bevel'} default 0
END_CAP_STYLE takes 0, 1 or 2, not "round".
Check that you are talking to one QGIS
Two installations in one process β a system QGIS plus a conda one, say β produce a registry populated from one and an API from the other.
import qgis
from qgis.core import Qgis
print("qgis pkg :", qgis.__file__)
print("processing :", processing.__file__)
print("version :", Qgis.QGIS_VERSION)
qgis pkg : /usr/share/qgis/python/qgis/__init__.py
processing : /usr/share/qgis/python/plugins/processing/__init__.py
version : 4.2.2-BelΓ©m do ParΓ‘
Both paths should sit under the same prefix. If they do not, fix the environment before touching the code.
Resolving algorithms on Rutland's schools
The data used on this page
Rutland's schools from Geofabrik's 1 January 2026 OpenStreetMap extract (Β© OpenStreetMap contributors, ODbL), in British National Grid. The page runs under QGIS 4.2; example 3 also runs a script in the qgis/qgis:ltr Docker image, which was QGIS 3.44.
import os
import subprocess
import sys
from pathlib import Path
import requests
from osgeo import gdal
gdal.UseExceptions()
Path("data").mkdir(exist_ok=True)
Path("out").mkdir(exist_ok=True)
if not Path("data/schools.gpkg").exists():
Path("data/rutland.shp.zip").write_bytes(requests.get(
"https://download.geofabrik.de/europe/united-kingdom/england/rutland-260101-free.shp.zip", timeout=300).content)
gdal.VectorTranslate("data/schools.gpkg", "/vsizip/data/rutland.shp.zip/gis_osm_pois_a_free_1.shp",
layerName="schools", dstSRS="EPSG:27700", reproject=True, where="fclass = 'school'")
os.environ.setdefault("QT_QPA_PLATFORM", "offscreen")
sys.path.append("/usr/share/qgis/python/plugins")
from qgis.core import QgsApplication, QgsProject, QgsProcessingFeedback, QgsVectorLayer
qgs = QgsApplication([], False)
qgs.initQgis()
print("after initQgis():", len(QgsApplication.processingRegistry().algorithms()), "algorithms")
from processing.core.Processing import Processing
import processing
Processing.initialize()
print("after Processing.initialize():", len(QgsApplication.processingRegistry().algorithms()), "algorithms")
print(QgsVectorLayer("data/schools.gpkg|layername=schools", "schools", "ogr").featureCount(), "schools")
after initQgis(): 0 algorithms
after Processing.initialize(): 772 algorithms
26 schools
Example 1: A reusable initialiser, and what the wrong order does
Each script runs in its own process, because a process gets one QgsApplication.
Path("qgis_boot.py").write_text('''
"""qgis_boot.py - initialise QGIS + Processing, or explain why not."""
import os, sys
from pathlib import Path
os.environ.setdefault("QT_QPA_PLATFORM", "offscreen")
PLUGIN_DIRS = [
"/usr/share/qgis/python/plugins",
"/Applications/QGIS.app/Contents/Resources/python/plugins",
]
def boot():
from qgis.core import QgsApplication
app = QgsApplication([], False)
app.initQgis()
for d in PLUGIN_DIRS:
if Path(d).is_dir() and d not in sys.path:
sys.path.append(d)
try:
from processing.core.Processing import Processing
except ImportError as exc:
raise RuntimeError(f"cannot import the processing plugin. Tried: {PLUGIN_DIRS}") from exc
Processing.initialize()
n = len(QgsApplication.processingRegistry().algorithms())
if n == 0:
raise RuntimeError("Processing registry is empty after initialize()")
print(f"processing ready: {n} algorithms")
return app
''')
Path("wrong_order.py").write_text('''
import os, sys
os.environ.setdefault("QT_QPA_PLATFORM", "offscreen")
sys.path.append("/usr/share/qgis/python/plugins")
from qgis.core import QgsApplication
from processing.core.Processing import Processing
Processing.initialize() # too early: no application yet
app = QgsApplication([], False)
app.initQgis()
import processing
try:
processing.run("native:buffer", {"INPUT": "data/schools.gpkg", "DISTANCE": 50, "OUTPUT": "TEMPORARY_OUTPUT"})
except Exception as exc:
print(type(exc).__name__ + ":", str(exc).strip())
app.exitQgis()
''')
for script in (["-c", "import qgis_boot; app = qgis_boot.boot(); app.exitQgis()"],
["-c", "import qgis_boot; qgis_boot.boot().exitQgis()"],
["wrong_order.py"]):
run = subprocess.run([sys.executable, *script], capture_output=True, text=True)
lines = [l for l in (run.stdout + run.stderr).splitlines() if l.strip() and not l.startswith("QThreadStorage")]
noise = sum(l == "Application path not initialized" for l in lines)
print(f"{script[-1]}: exit {run.returncode}" + (f", 'Application path not initialized' x {noise}" if noise else ""))
for line in lines:
if line != "Application path not initialized":
print(" ", line)
import qgis_boot; app = qgis_boot.boot(); app.exitQgis(): exit 0
processing ready: 772 algorithms
import qgis_boot; qgis_boot.boot().exitQgis(): exit -11
wrong_order.py: exit 0, 'Application path not initialized' x 55
QgsProcessingException: Error: Algorithm native:buffer not found
The wrong order raised nothing at the point of the mistake. The only signs were a screenful of warnings and, later, an algorithm that is not found. The middle run is a different trap with the same helper: chaining boot().exitQgis() in one expression leaves the application to be destroyed the moment the call returns, and the process died with a segmentation fault (exit -11) before printing anything. Keep the application in a variable for the life of the script.
Example 2: Resolve an algorithm before running it
def require_algorithm(alg_id: str):
reg = QgsApplication.processingRegistry()
alg = reg.algorithmById(alg_id)
if alg is not None:
return alg
needle = alg_id.split(":")[-1].lower()
close = [a.id() for a in reg.algorithms() if needle in a.id().lower()]
raise ValueError(
f"algorithm {alg_id!r} not found in QGIS {Qgis.QGIS_VERSION.split('-')[0]}. "
f"Providers loaded: {[p.id() for p in reg.providers()]}. "
f"Did you mean: {close[:5]}?"
)
from qgis.core import Qgis
print(require_algorithm("native:buffer").id())
print(require_algorithm("qgis:selectbyexpression").id(), "(asked for qgis:selectbyexpression)")
for wrong in ("qgis:joinattributes", "native:bufer"):
try:
require_algorithm(wrong)
except ValueError as exc:
print(exc)
native:buffer
native:selectbyexpression (asked for qgis:selectbyexpression)
algorithm 'qgis:joinattributes' not found in QGIS 4.2.2. Providers loaded: ['3d', 'gdal', 'grass', 'model', 'native', 'pdal', 'project', 'qgis', 'script']. Did you mean: ['native:joinattributesbylocation', 'native:joinattributestable']?
algorithm 'native:bufer' not found in QGIS 4.2.2. Providers loaded: ['3d', 'gdal', 'grass', 'model', 'native', 'pdal', 'project', 'qgis', 'script']. Did you mean: []?
Two things to notice. algorithmById() resolves the old qgis: id and hands back the native: algorithm, so the id you asked for and the id you got differ. And the suggestions only help when the misspelling is a substring: native:bufer finds nothing, because bufer is not in buffer. Printing the provider list is what makes that message useful anyway.
Example 3: Dump the catalogue, and compare it with the server's
import csv
reg = QgsApplication.processingRegistry()
with open("algorithms_4.2.csv", "w", newline="", encoding="utf-8") as fh:
w = csv.writer(fh)
w.writerow(["id", "display_name", "provider", "group"])
for alg in sorted(reg.algorithms(), key=lambda a: a.id()):
w.writerow([alg.id(), alg.displayName(), alg.provider().id(), alg.group()])
ids_42 = {a.id() for a in reg.algorithms()}
Path("dump_ids.py").write_text('''
import os, sys
os.environ.setdefault("QT_QPA_PLATFORM", "offscreen")
sys.path.append("/usr/share/qgis/python/plugins")
from qgis.core import QgsApplication, Qgis
app = QgsApplication([], False); app.initQgis()
from processing.core.Processing import Processing
Processing.initialize()
reg = QgsApplication.processingRegistry()
print(Qgis.QGIS_VERSION)
print("\\n".join(sorted(a.id() for a in reg.algorithms())))
''')
docker = subprocess.run(["docker", "run", "--rm", "-v", f"{Path.cwd()}:/work", "-w", "/work",
"--user", f"{os.getuid()}:{os.getgid()}", "-e", "HOME=/tmp", "-e", "QT_QPA_PLATFORM=offscreen",
"qgis/qgis:ltr", "python3", "dump_ids.py"], capture_output=True, text=True)
server_version, *server_ids = docker.stdout.split()
ids_344 = set(server_ids)
print(f"QGIS 4.2: {len(ids_42)} algorithms; QGIS {server_version.split('-')[0]} (qgis/qgis:ltr): {len(ids_344)}")
newer = sorted(ids_42 - ids_344)
print("in 4.2, missing on the LTR:", {p: sum(i.startswith(p + ":") for i in newer) for p in ("native", "pdal", "gdal")})
moved = sorted(i for i in ids_344 - ids_42)
print("on the LTR, gone from 4.2's list:", len(moved), "- e.g.", moved[:3])
print("do the old ids still resolve in 4.2?",
all(reg.algorithmById(i) is not None for i in moved),
"->", reg.algorithmById(moved[0]).id())
QGIS 4.2: 772 algorithms; QGIS 3.44.15 (qgis/qgis:ltr): 730
in 4.2, missing on the LTR: {'native': 29, 'pdal': 24, 'gdal': 2}
on the LTR, gone from 4.2's list: 13 - e.g. ['qgis:distancematrix', 'qgis:heatmapkerneldensityestimation', 'qgis:hypsometriccurves']
do the old ids still resolve in 4.2? True -> native:distancematrix
A local catalogue is faster to search than the documentation and always matches the installed version. The comparison is the one worth automating: if the machine that develops the pipeline and the machine that runs it are on different QGIS releases, diff their catalogues before the first deployment, not after the first failure.
Example 4: The same checks from the shell
def qgis_process(*args):
run = subprocess.run(["qgis_process", *args], capture_output=True, text=True,
env=dict(os.environ, QT_QPA_PLATFORM="offscreen"))
return [l for l in (run.stdout + run.stderr).splitlines() if l.strip()]
listing = qgis_process("list")
print(sum("buffer" in l.lower() for l in listing if "\t" in l), "listed ids mention buffer")
print(qgis_process("help", "native:buffer")[0])
print(next(l for l in qgis_process("run", "native:buffer", "--", "INPUT=data/schools.gpkg|layername=schools",
"DISTANCE=50", "OUTPUT=out/qp_buffer.gpkg") if l.startswith("OUTPUT")))
print(qgis_process("run", "native:bufer")[-1])
11 listed ids mention buffer
Buffer (native:buffer)
OUTPUT: out/qp_buffer.gpkg
Algorithm native:bufer not found!
qgis_process initialises QGIS and Processing for you, so if an id works there and not in your script, the problem is your initialisation rather than the id. Its own error for an unknown id is worded differently from the Python one β not found!, with an exclamation mark β which is worth knowing when grepping logs.
Example 5: What the gdal: and grass: providers actually run
import re
class CommandLog(QgsProcessingFeedback):
"""Keep the programs a provider runs and the errors they report."""
def __init__(self):
super().__init__()
self.commands, self.errors = [], []
def pushCommandInfo(self, info):
self.commands.append(info.split()[0])
def reportError(self, error, fatalError=False):
self.errors.append(error.strip())
schools = "data/schools.gpkg|layername=schools"
runs = {
"gdal:buffervectors": {"INPUT": schools, "DISTANCE": 100, "OUTPUT": "out/gdal_buffer.gpkg"},
"gdal:buffervectors + GEOMETRY": {"INPUT": schools, "GEOMETRY": "geom", "DISTANCE": 100,
"OUTPUT": "out/gdal_buffer_geom.gpkg"},
"grass:v.buffer": {"input": schools, "distance": 100, "output": "out/grass_buffer.gpkg"},
"native:buffer": {"INPUT": schools, "DISTANCE": 100, "OUTPUT": "out/native_buffer.gpkg"},
}
for label, params in runs.items():
log = CommandLog()
result = processing.run(label.split()[0], params, feedback=log)
n = QgsVectorLayer(next(iter(result.values())), "out", "ogr").featureCount()
print(f"{label:31} ran {log.commands or 'in-process'} -> {n} features")
for error in log.errors[:1]:
message = re.sub(r"^.*?(ERROR|Warning) \d+: ", "", error).split("): ")[-1]
print(" reported:", message[:100])
gdal:buffervectors ran ['ogr2ogr'] -> -2 features
reported: no such column: geometry
gdal:buffervectors + GEOMETRY ran ['ogr2ogr'] -> 26 features
reported: A geometry of type MULTIPOLYGON is inserted into layer SELECT of geometry type POLYGON, which is not
grass:v.buffer ran ['g.proj', 'v.in.ogr', 'g.region', 'v.buffer', 'v.out.ogr'] -> 20 features
native:buffer ran in-process -> 26 features
A gdal: algorithm is a command line for ogr2ogr or a gdal_* tool, and a grass: one is a sequence of GRASS modules with an import at the start and an export at the end. That is why their availability is a property of the machine β the binaries have to be there β and it has two consequences the run above shows.
The first gdal:buffervectors call failed and processing.run() did not raise. The algorithm writes SQL against a geometry column called geometry; this GeoPackage's column is geom, ogr2ogr exited with an error, and the call returned an output path to a file with no layer in it (a feature count of -2). The error only reached the feedback object. Passing GEOMETRY fixed it, though ogr2ogr still reported multipolygons going into a layer it had declared as polygons β and named that layer SELECT, after the SQL that made it. Check the output of a gdal: algorithm, not just the return value.
The second is that the providers are different programs, not different spellings: GRASS's v.buffer dissolved the overlapping school buffers and returned fewer features than the 26 schools that went in, where native:buffer kept one per school. Swapping one provider's algorithm for another's because the name matches changes the result.
The page's QGIS session ends here:
QgsProject.instance().clear()
qgs.exitQgis()
print("QGIS closed")
QGIS closed
A registry, not a namespace
Processing is a registry, not a namespace. At start-up it is empty; Processing.initialize() asks each provider to enumerate its algorithms and register them under provider:name. processing.run() then looks the string up in that registry. "Algorithm not found" is therefore a dictionary miss, and there are exactly two ways to get one: nothing put the key in, or you asked for a key this installation does not have.
Ordering matters because the providers need a live application. initQgis() sets up the application's paths, the CRS database and the expression engine, and Processing.initialize() builds on them. Run it first and it finds no application path β hence the repeated warning β and whatever it managed to register did not survive: the registry was empty again after initQgis(), and a second initialize() call was needed to fill it.
The id itself has history. Many algorithms began as Python implementations under the qgis: prefix and were rewritten in C++ under native:. QGIS keeps the old id working as an alias after a port β all 13 ported between 3.44 and 4.2 still resolved β but the alias only runs forward in time. That asymmetry is the usual shape of this error in production: a developer on the latest release copies an id from the History panel, and the pinned LTR in the pipeline's container has never heard of it.
Finally, provider availability is a property of the installation, not the code. In both builds tested, GRASS was installed and Processing.initialize() registered its 307 algorithms without being asked; PDAL was in the 4.2 package and not in the 3.44 image. Checking for the ids a pipeline needs at start-up, and failing with the provider list, costs a few lines and replaces a confusing failure on a machine you cannot see with a clear one.
Run versus runAndLoadResults, enums and profiles
processing.runvsprocessing.runAndLoadResults: the latter works headless, but "load" means adding the result toQgsProject.instance()β in a standalone run it returned a layer id and put a layer calledBufferedinto a project nobody sees. Userunand keep the output.- Enum parameters take integers:
PREDICATE: [0]means "intersects".algorithmHelp()lists the mapping; the names in the dialog are labels only. - Layer parameters accept several forms: a file path, a
path|layername=xURI, or aQgsVectorLayerobject. The URI form is what History records for multi-layer files. TEMPORARY_OUTPUTneeds a live context: the result layer lives in the Processing context and disappears with it. Write it out before teardown.- Model and script algorithms come from the profile: the
modelandscriptproviders are always registered, and in a fresh headless profile they held no algorithms. A model an analyst saved in their desktop profile is not visible to a script running under another user. - Pin the QGIS version in Docker if a pipeline must keep working unattended, and develop against the same version.
- An old
qgis:id that still works has been redirected;algorithmById()returns thenative:algorithm. Update the id when convenient, but it is not what breaks.
Internal links
- How to Run QGIS Processing Algorithms from Python
- How to Automate QGIS with Python (PyQGIS): The Complete Workflow
- How to Run a PyQGIS Script Headless Without Opening QGIS
- How to Build a QGIS Processing Model and Run It from Python
- PyQGIS Processing Output Is Empty: How to Fix It
- How to Fix "ModuleNotFoundError: No module named 'qgis'"
FAQ
Why does the algorithm work in the Toolbox but not in my script?
Because the Toolbox runs inside a QGIS that has already initialised Processing and loaded every enabled provider. A standalone script must call QgsApplication.initQgis() and then Processing.initialize() itself.
Should I use qgis: or native:?
Whichever the QGIS that runs the script has. A qgis: id that was ported to C++ keeps working as an alias on newer releases, but the new native: id does not exist on older ones: 13 algorithms that are native: in 4.2 are only qgis: in 3.44. If one script must run on both, use the old id or check the registry first.
How do I find the correct parameter names?
Run processing.algorithmHelp("native:buffer"), or qgis_process help native:buffer from a shell. Both list every parameter, its type, and the integer values behind enums.
Why are GRASS or SAGA algorithms missing?
GRASS algorithms need GRASS installed on the machine; where it was, Processing.initialize() registered all 307 of them in both QGIS 3.44 and 4.2 without further code. SAGA comes from a separate plugin (SAGA NextGen) that has to be installed and loaded, and PDAL algorithms depend on how QGIS was packaged β the 3.44 Docker image had none.
What does "Could not load source layer for INPUT" mean?
The id resolved but the input value did not. Check the path, and for multi-layer files use the URI form file.gpkg|layername=parcels β the same string the History panel records.
Can I list every available algorithm from the command line?
Yes: qgis_process list prints them grouped by provider, and qgis_process help <id> prints the parameters. This is the quickest way to check what a server build actually has.
Why did my script break after a QGIS upgrade?
Algorithm ids and parameter names do change between releases: between 3.44 and 4.2, 13 algorithms moved from qgis: to native: and 29 new native: ids appeared. Pin the QGIS version for scheduled pipelines, develop on the same version, and resolve ids through a helper that fails loudly with the provider list when one is missing.