invoke-ai/InvokeAI · error · ValueError
Invalid external model source: '{source_stripped}'
Error message
Invalid external model source: '{source_stripped}' What it means
_guess_source() parses a free-form string into a ModelSource. For strings starting with 'external://', it splits into provider_id/model_id on '/'; if either part is missing (no slash, empty provider, or empty model id), it raises ValueError("Invalid external model source: '...'").
Source
Thrown at invokeai/app/services/model_install/model_install_default.py:883
except ValueError:
pass
return [RemoteModelFile(url=self._normalize_huggingface_blob_url(source.url), path=Path("."), size=0)], None
raise Exception(f"No files associated with {source}")
def _guess_source(self, source: str) -> ModelSource:
"""Turn a source string into a ModelSource object."""
variants = "|".join(ModelRepoVariant.__members__.values())
hf_repoid_re = f"^([^/:]+/[^/:]+)(?::({variants})?(?::/?([^:]+))?)?$"
source_obj: Optional[StringLikeSource] = None
source_stripped = source.strip('"')
if source_stripped.startswith("external://"):
external_id = source_stripped.removeprefix("external://")
provider_id, _, provider_model_id = external_id.partition("/")
if not provider_id or not provider_model_id:
raise ValueError(f"Invalid external model source: '{source_stripped}'")
source_obj = ExternalModelSource(provider_id=provider_id, provider_model_id=provider_model_id)
elif Path(source_stripped).exists(): # A local file or directory
source_obj = LocalModelSource(path=Path(source_stripped))
elif match := re.match(hf_repoid_re, source):
source_obj = HFModelSource(
repo_id=match.group(1),
variant=ModelRepoVariant(match.group(2)) if match.group(2) else None, # pass None rather than ''
subfolder=Path(match.group(3)) if match.group(3) else None,
)
elif re.match(r"^https?://[^/]+", source):
source_obj = URLModelSource(
url=Url(source),
)
else:
raise ValueError(f"Unsupported model source: '{source}'")
return source_obj
# --------------------------------------------------------------------------------------------View on GitHub (pinned to 0b6a024f2f)
Solutions
- Use the full form 'external://<provider_id>/<provider_model_id>' with exactly one slash separating non-empty parts.
- Check that the provider supports the model and that the provider_model_id is correct (e.g. 'external://openai/dall-e-3').
- If the id contains slashes, avoid the external:// string form and pass ExternalModelSource(provider_id=..., provider_model_id=...) directly.
- Trim whitespace/quotes from user input before calling heuristic_import().
Example fix
// before
service.heuristic_import('external://openai')
// after
service.heuristic_import('external://openai/dall-e-3') Defensive patterns
Strategy: validation
Validate before calling
import re
EXTERNAL_RE = re.compile(r'^external://[^/]+/[^/]+/?$')
if source.startswith('external://') and not EXTERNAL_RE.match(source.strip('"')):
raise ValueError('Use external://<provider_id>/<provider_model_id>') Type guard
def is_valid_external_source(s: str) -> bool:
s = s.strip('"')
if not s.startswith('external://'):
return False
provider, _, model_id = s.removeprefix('external://').partition('/')
return bool(provider) and bool(model_id) Try / catch
try:
source_obj = service.heuristic_import(user_input)
except ValueError as e:
if 'Invalid external model source' in str(e):
source_obj = None # prompt user for provider/model-id Prevention
- Always emit external:// sources as 'provider/model' with both parts non-empty.
- Trim quotes/whitespace from user input before parsing.
- For provider ids containing slashes, construct ExternalModelSource directly.
- Validate UI-generated strings with a regex before submission.
When it happens
Trigger: heuristic_import('external://') or 'external://openai' (missing model id or provider); extra slashes like 'external://provider/' or 'external:///model'; whitespace/quote handling leaves a malformed string; typo such as 'external:/provider/model'.
Common situations: UI/CLI users typing an external:// shorthand manually; templated strings where the model id variable is empty; provider ids containing slashes (not supported by the simple partition).
Related errors
- per_layer_weights must be comma-separated numbers: {e}
- Unknown image subfolder strategy: {strategy}
- Unsupported model source: '{source}'
- encode_caption_for_pid requires at least one caption.
- Invalid or expired token
AI-assisted analysis of invoke-ai/InvokeAI@0b6a024f2f (2026-08-29).
Data as JSON: /api/errors/cbbe21e80ee16ef8.
Report an issue: GitHub.