diff --git a/libs/core/langchain_core/_api/deprecation.py b/libs/core/langchain_core/_api/deprecation.py index b48215d0d6c..602732e7456 100644 --- a/libs/core/langchain_core/_api/deprecation.py +++ b/libs/core/langchain_core/_api/deprecation.py @@ -214,7 +214,7 @@ def deprecated( if not _obj_type: _obj_type = "attribute" if not _name: - raise ValueError() + raise ValueError(f"Field {obj} must have a name to be deprecated.") old_doc = obj.description def finalize(wrapper: Callable[..., Any], new_doc: str) -> T: diff --git a/libs/core/langchain_core/prompts/chat.py b/libs/core/langchain_core/prompts/chat.py index a53f1bb251c..ecd656a7ccc 100644 --- a/libs/core/langchain_core/prompts/chat.py +++ b/libs/core/langchain_core/prompts/chat.py @@ -551,13 +551,13 @@ class _StringImageMessagePromptTemplate(BaseMessagePromptTemplate): input_variables=input_variables, template=img_template ) else: - raise ValueError() + raise ValueError(f"Invalid image template: {tmpl}") prompt.append(img_template_obj) else: - raise ValueError() + raise ValueError(f"Invalid template: {tmpl}") return cls(prompt=prompt, **kwargs) else: - raise ValueError() + raise ValueError(f"Invalid template: {template}") @classmethod def from_template_file( diff --git a/libs/core/langchain_core/runnables/history.py b/libs/core/langchain_core/runnables/history.py index e169bd9a05d..e3197bec900 100644 --- a/libs/core/langchain_core/runnables/history.py +++ b/libs/core/langchain_core/runnables/history.py @@ -433,7 +433,9 @@ class RunnableWithMessageHistory(RunnableBindingBase): # This occurs for chat models - since we batch inputs if isinstance(input_val[0], list): if len(input_val) != 1: - raise ValueError() + raise ValueError( + f"Expected a single list of messages. Got {input_val}." + ) return input_val[0] return list(input_val) else: diff --git a/libs/core/tests/unit_tests/runnables/test_runnable_events_v2.py b/libs/core/tests/unit_tests/runnables/test_runnable_events_v2.py index 6132c0efb0d..59fc49ca5ea 100644 --- a/libs/core/tests/unit_tests/runnables/test_runnable_events_v2.py +++ b/libs/core/tests/unit_tests/runnables/test_runnable_events_v2.py @@ -1889,6 +1889,25 @@ async def test_runnable_with_message_history() -> None: input_messages_key="question", history_messages_key="history", ) + + # patch with_message_history._get_output_messages to listen for errors + # so we can raise them in this main thread + raised_errors = [] + + def collect_errors(fn): # type: ignore + nonlocal raised_errors + + def _get_output_messages(*args, **kwargs): # type: ignore + try: + return fn(*args, **kwargs) + except Exception as e: + raised_errors.append(e) + raise e + + return _get_output_messages + + old_ref = with_message_history._get_output_messages + with_message_history.__dict__["_get_output_messages"] = collect_errors(old_ref) await with_message_history.with_config( {"configurable": {"session_id": "session-123"}} ).ainvoke({"question": "hello"}) @@ -1911,6 +1930,7 @@ async def test_runnable_with_message_history() -> None: AIMessage(content="world", id="ai4"), ] } + assert not raised_errors EXPECTED_EVENTS = [