invoke-ai/InvokeAI · error · HTTPException
No external provider config fields provided
Error message
No external provider config fields provided
What it means
set_external_provider_config returns 400 when the request body contains no fields that actually map to external-provider config keys (e.g. api_key / base_url for the provider). After building the updates dict from update.api_key/update.base_url, an empty dict means nothing was provided, so the server refuses the no-op call.
Source
Thrown at invokeai/app/api/routers/app_info.py:331
response_model=ExternalProviderConfigModel,
)
def set_external_provider_config(
_: AdminUserOrDefault,
provider_id: str = Path(description="The external provider identifier"),
update: ExternalProviderConfigUpdate = Body(description="External provider configuration settings"),
) -> ExternalProviderConfigModel:
api_key_field, base_url_field = _get_external_provider_fields(provider_id)
updates: dict[str, str | None] = {}
if update.api_key is not None:
api_key = update.api_key.strip()
updates[api_key_field] = api_key or None
if update.base_url is not None:
base_url = update.base_url.strip()
updates[base_url_field] = base_url or None
if not updates:
raise HTTPException(status_code=400, detail="No external provider config fields provided")
api_key_removed = update.api_key is not None and updates.get(api_key_field) is None
_apply_external_provider_update(updates)
if api_key_removed:
_remove_external_models_for_provider(provider_id)
return _build_external_provider_config(provider_id, get_config())
@app_router.delete(
"/external_providers/config/{provider_id}",
operation_id="reset_external_provider_config",
status_code=200,
response_model=ExternalProviderConfigModel,
)
def reset_external_provider_config(
_: AdminUserOrDefault,
provider_id: str = Path(description="The external provider identifier"),
) -> ExternalProviderConfigModel:View on GitHub (pinned to 0b6a024f2f)
Solutions
- Include at least one real field in the body: api_key and/or base_url
- To CLEAR a field send an empty string ("") rather than null (empty string maps to None and counts as an update)
- Fix the client to omit the call entirely when nothing changed
- Check which fields the target provider supports via its config schema and send one of those
Example fix
// before
await fetch(url, { method: 'POST', body: JSON.stringify({ api_key: null, base_url: null }) });
// after
await fetch(url, { method: 'POST', body: JSON.stringify({ api_key: 'sk-...' }) }); Defensive patterns
Strategy: validation
Validate before calling
def validate_provider_update(update: dict) -> bool:
fields = {'api_key', 'base_url'}
return any(update.get(f) is not None for f in fields) # at least one real value
if not validate_provider_update(payload):
raise ValueError('Supply api_key and/or base_url (use "" to clear)') Type guard
def has_provider_field(update: dict) -> bool:
return isinstance(update, dict) and any(
v is not None for k, v in update.items() if k in ('api_key', 'base_url')
) Try / catch
try:
resp = requests.post(url, json=payload)
resp.raise_for_status()
except requests.HTTPError as e:
if e.response.status_code == 400 and 'No external provider' in e.response.json().get('detail', ''):
skip_call = True # nothing to update Prevention
- Only call the endpoint when at least one field actually changed
- Send "" (empty string) to clear a field, not null
- Diff the payload against current config before posting
- Omit all-null optional fields when building the request body
When it happens
Trigger: POSTing to the external-provider config endpoint with a body where every optional field is None/absent (e.g. {} or {"api_key": null, "base_url": null}), so `updates` stays empty.
Common situations: Frontend sending an untouched form; client serializing all-None optional fields; a provider whose only fields are api_key/base_url both left blank; generic code paths reusing a payload template across providers.
Related errors
- str(e)
- str(e) (ValueError from user service update, e.g. LastAdmini
- Current password is required to set a new password
- Invalid request: Must provide either 'all' or both 'offset'
- No images or board id specified.
AI-assisted analysis of invoke-ai/InvokeAI@0b6a024f2f (2026-08-29).
Data as JSON: /api/errors/c6d0e8c9969b9a69.
Report an issue: GitHub.