AUTOMATIC1111/stable-diffusion-webui · error · HTTPException
Cannot have a selectable script in the always on scripts par
Error message
Cannot have a selectable script in the always on scripts params
What it means
HTTP 422 raised in initscript_args when a script resolved from request.alwayson_scripts has alwayson == False, i.e. it is a selectable script (appears in the Scripts dropdown) rather than an always-on one. The API enforces the split: selectable scripts go through script_name/script_args, always-on ones through alwayson_scripts, and mixing them is rejected.
Source
Thrown at modules/api/api.py:355
if input_script_args is not None:
for index, value in input_script_args.items():
script_args[index] = value
# position 0 in script_arg is the idx+1 of the selectable script that is going to be run when using scripts.scripts_*2img.run()
if selectable_scripts:
script_args[selectable_scripts.args_from:selectable_scripts.args_to] = request.script_args
script_args[0] = selectable_idx + 1
# Now check for always on scripts
if request.alwayson_scripts:
for alwayson_script_name in request.alwayson_scripts.keys():
alwayson_script = self.get_script(alwayson_script_name, script_runner)
if alwayson_script is None:
raise HTTPException(status_code=422, detail=f"always on script {alwayson_script_name} not found")
# Selectable script in always on script param check
if alwayson_script.alwayson is False:
raise HTTPException(status_code=422, detail="Cannot have a selectable script in the always on scripts params")
# always on script with no arg should always run so you don't really need to add them to the requests
if "args" in request.alwayson_scripts[alwayson_script_name]:
# min between arg length in scriptrunner and arg length in the request
for idx in range(0, min((alwayson_script.args_to - alwayson_script.args_from), len(request.alwayson_scripts[alwayson_script_name]["args"]))):
script_args[alwayson_script.args_from + idx] = request.alwayson_scripts[alwayson_script_name]["args"][idx]
return script_args
def apply_infotext(self, request, tabname, *, script_runner=None, mentioned_script_args=None):
"""Processes `infotext` field from the `request`, and sets other fields of the `request` according to what's in infotext.
If request already has a field set, and that field is encountered in infotext too, the value from infotext is ignored.
Additionally, fills `mentioned_script_args` dict with index: value pairs for script arguments read from infotext.
"""
if not request.infotext:
return {}
View on GitHub (pinned to 82a973c043)
Solutions
- Pass selectable scripts via the top-level script_name + script_args fields instead of alwayson_scripts
- If you own the script, set self.alwayson = True (and a name) in its Script class so it qualifies as always-on
- Pick a genuinely always-on script (e.g. controlnet-style extension scripts) for the alwayson_scripts map
Example fix
# before
json={'alwayson_scripts':{'X/Y/Z plot':{'args':[]}}}
# after
json={'script_name':'X/Y/Z plot','script_args':[...]}
# extension authors:
# class Script(scripts.Script):
# def __init__(self):
# self.alwayson = True Defensive patterns
Strategy: validation
Validate before calling
selectable = set(scripts_api['txt2img']) | set(scripts_api['img2img'])
for name in payload.get('alwayson_scripts', {}):
if name in selectable:
payload['script_name'] = name
payload['script_args'] = payload['alwayson_scripts'].pop(name).get('args', []) Type guard
def is_selectable_script(name: str, selectable: set[str]) -> bool:
return name in selectable Try / catch
if resp.status_code == 422 and 'selectable script in the always on' in resp.json()['detail']:
move_selectable_scripts_out_of_alwayson(payload)
resp = requests.post(url, json=payload, auth=auth) Prevention
- Route dropdown scripts through script_name/script_args only
- Extension authors: set self.alwayson = True for scripts meant to be always-on
- Test payloads against /sdapi/v1/scripts metadata in CI
When it happens
Trigger: POST /sdapi/v1/txt2img with {"alwayson_scripts": {"X/Y/Z plot": {...}}} (or any other dropdown script like Prompt matrix); the script exists and is found, but its alwayson flag is False because it was registered as selectable.
Common situations: Clients migrating from script_name usage trying to force-run dropdown scripts always-on; authors of custom extension scripts who forgot to set self.alwayson = True in the script class; script category changes between versions.
Related errors
- always on script {alwayson_script_name} not found
- Script '{name}' not found
- Sampler not found
- Invalid encoded image
- Init image not found
AI-assisted analysis of AUTOMATIC1111/stable-diffusion-webui@82a973c043 (2026-08-14).
Data as JSON: /api/errors/961f1f31dacd067f.
Report an issue: GitHub.