mlflow/mlflow · error · MlflowException

Cannot load runnable without a config file. Got path {config

Error message

Cannot load runnable without a config file. Got path {config_path}.

What it means

MLflow's runnable loader (_load_model_from_config) reconstructs a LangChain runnable from a YAML or JSON config file saved alongside the model. If the given config_path ends in neither `.yaml` nor `.json`, MLflow cannot parse it and raises this MlflowException. The config file is the sole source of the runnable's `_type` and structure.

Source

Thrown at mlflow/langchain/runnables.py:75

@patch_langchain_type_to_cls_dict
def _load_model_from_config(path, model_config):
    from langchain.chains.loading import type_to_loader_dict as chains_type_to_loader_dict
    from langchain.llms import get_type_to_cls_dict as llms_get_type_to_cls_dict

    try:
        from langchain.prompts.loading import type_to_loader_dict as prompts_types
    except ImportError:
        prompts_types = {"prompt", "few_shot_prompt"}

    config_path = os.path.join(path, model_config.get(_MODEL_DATA_KEY, _MODEL_DATA_YAML_FILE_NAME))
    # Load runnables from config file
    if config_path.endswith(".yaml"):
        config = _load_from_yaml(config_path)
    elif config_path.endswith(".json"):
        config = _load_from_json(config_path)
    else:
        raise MlflowException(
            f"Cannot load runnable without a config file. Got path {config_path}."
        )
    _type = config.get("_type")
    if _type in chains_type_to_loader_dict:
        from langchain.chains.loading import load_chain

        return _patch_loader(load_chain)(config_path)
    elif _type in prompts_types:
        from langchain.prompts.loading import load_prompt

        return load_prompt(config_path)
    elif _type in llms_get_type_to_cls_dict():
        from langchain_community.llms.loading import load_llm

        return _patch_loader(load_llm)(config_path)
    elif _type in custom_type_to_loader_dict():
        return custom_type_to_loader_dict()[_type](config)
    raise MlflowException(f"Unsupported type {_type} for loading.")

View on GitHub (pinned to 6a27f2decc)

Solutions

  1. Point config_path at the actual saved config file with a .yaml or .json extension (typically `<model_path>/model.yaml`).
  2. Rename the config file to end in .yaml or .json if it was renamed.
  3. If the model was saved as pickle, use the pickle load key path instead of the config loader.

Example fix

// before
model = _load_model_from_config("models/runnable.yml")
// after
model = _load_model_from_config("models/runnable.yaml")
Defensive patterns

Strategy: validation

Validate before calling

p = pathlib.Path(config_path)
assert p.is_file() and p.suffix in (".yaml", ".json"), f"need .yaml/.json config, got {config_path}"

Type guard

def is_valid_config_path(path: str) -> bool:
    p = pathlib.Path(path)
    return p.is_file() and p.suffix.lower() in {".yaml", ".json"}

Try / catch

try:
    model = _load_model_from_config(config_path)
except MlflowException as e:
    if "without a config file" in str(e):
        config_path = str(pathlib.Path(config_path).with_suffix(".yaml"))
        model = _load_model_from_config(config_path)
    else:
        raise

Prevention

When it happens

Trigger: Calling _load_model_from_config (via _load_model_from_path / _save_internal_runnables round-trip) with a path to a `.yml`, `.txt`, `.pkl`, or extensionless file, or to a directory instead of a config file.

Common situations: Renaming the saved config file (config.yaml -> config.yml); pointing the loader at the model directory instead of the config file; custom save pipelines writing JSON with an unusual extension.

Related errors


AI-assisted analysis of mlflow/mlflow@6a27f2decc (2026-08-29). Data as JSON: /api/errors/38dd068fe81da9f4. Report an issue: GitHub.