invoke-ai/InvokeAI · error · ValueError
Unsupported model source: '{source}'
Error message
Unsupported model source: '{source}' What it means
_guess_source() is the catch-all parser for model source strings. After checking external://, local paths, HuggingFace repo ids, and repo-file patterns, it treats only http(s) URLs as URLModelSource. Anything else raises ValueError('Unsupported model source: ...'), meaning the string matches none of the recognized source patterns.
Source
Thrown at invokeai/app/services/model_install/model_install_default.py:898
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
# --------------------------------------------------------------------------------------------
# Internal functions that manage the installer threads
# --------------------------------------------------------------------------------------------
def _start_installer_thread(self) -> None:
self._install_thread = threading.Thread(target=self._install_next_item, daemon=True)
self._install_thread.start()
self._running = True
@staticmethod
def _safe_rmtree(path: Path, logger: Any) -> None:
"""Remove a directory tree with retry logic for Windows file locking issues.
On Windows, memory-mapped files may not be immediately released even after
the file handle is closed. This function retries the removal with garbage
collection to help release any lingering references.
"""View on GitHub (pinned to 0b6a024f2f)
Solutions
- Use a fully qualified HuggingFace repo id 'org/repo' (optionally ':variant:subfolder').
- For downloads, use an http(s) URL to the file or repo.
- If it's a local model, ensure the path exists on the machine running the service and is absolute.
- Or construct the appropriate ModelSource object explicitly (HFModelSource/URLModelSource/LocalModelSource) instead of a string.
Example fix
// before
service.heuristic_import('stable-diffusion-v1-5')
// after
service.heuristic_import('stable-diffusion-v1-5/stable-diffusion-v1-5') # or full https URL / existing local path Defensive patterns
Strategy: validation
Validate before calling
import re, os
HF_RE = re.compile(r'^[^/:]+/[^/:]+')
ok = bool(HF_RE.match(s) or re.match(r'^https?://', s) or (os.path.exists(s.strip('"')))) Type guard
def is_recognizable_source(s: str) -> bool:
s2 = s.strip('"')
return (s2.startswith('external://')
or os.path.exists(s2)
or bool(re.match(r'^[^/:]+/[^/:]+', s))
or bool(re.match(r'^https?://', s))) Try / catch
try:
source_obj = service.heuristic_import(user_string)
except ValueError as e:
if 'Unsupported model source' in str(e):
source_obj = HFModelSource(repo_id=f'owner/{user_string}') # normalize bare names Prevention
- Always pass HF sources as 'owner/repo', never a bare model name.
- Use http(s) URLs only; convert s3:// or file:// URIs beforehand.
- Ensure local paths exist on the service host, not just the client.
- When in doubt, construct an explicit ModelSource object instead of a string.
When it happens
Trigger: Passing a bare model name not matching the HF repoid regex (no 'org/name' shape); ftp:// or other non-http URLs; typo'd repoids like 'authorname' without slash; Windows paths with backslashes that don't exist as local paths on this machine.
Common situations: Users pasting a model page slug like 'stable-diffusion-v1-5' without the owner prefix; scripts passing 's3://bucket/model' or 'file:///...' URIs; local path that exists on the user's machine but not the server's filesystem.
Related errors
- per_layer_weights must be comma-separated numbers: {e}
- Invalid external model source: '{source_stripped}'
- No external provider config fields provided
- str(e)
- str(e) (ValueError from user service update, e.g. LastAdmini
AI-assisted analysis of invoke-ai/InvokeAI@0b6a024f2f (2026-08-29).
Data as JSON: /api/errors/079b63e22a4759cd.
Report an issue: GitHub.