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

  1. Use the full form 'external://<provider_id>/<provider_model_id>' with exactly one slash separating non-empty parts.
  2. Check that the provider supports the model and that the provider_model_id is correct (e.g. 'external://openai/dall-e-3').
  3. If the id contains slashes, avoid the external:// string form and pass ExternalModelSource(provider_id=..., provider_model_id=...) directly.
  4. 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

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


AI-assisted analysis of invoke-ai/InvokeAI@0b6a024f2f (2026-08-29). Data as JSON: /api/errors/cbbe21e80ee16ef8. Report an issue: GitHub.