Suppress "Placeholders have not been resolved" warning when MessagesPlaceholder use is intentional (LangChain integration)
Maintainers usually reply within 1 day
@hassiebp is already working on this.
Since May 22, 2026.
Assessment
This issue has not been assessed yet.
Description
Summary
ChatPromptClient.compile() (and get_langchain_prompt() which calls it
under the hood) unconditionally logs:
Placeholders ['...'] have not been resolved. Pass them as keyword arguments to compile().
even when leaving placeholders unresolved is intentional — i.e. the
caller follows the officially documented LangChain integration pattern
where unresolved placeholders are deliberately returned as
MessagesPlaceholder for LangChain's ChatPromptTemplate to resolve at
.invoke() time.
Result: production logs are flooded with one WARNING per request, masking
real signals.
Reproduction (langfuse 4.6.1, official docs example)
from langfuse import get_client
from langchain_core.prompts import ChatPromptTemplate
langfuse = get_client()
# Create a chat prompt with a placeholder (per docs example)
langfuse.create_prompt(
name="movie-critic-chat",
type="chat",
prompt=[
{"role": "system", "content": "You are an expert movie critic"},
{"type": "placeholder", "name": "chat_history"},
{"role": "user", "content": "What should I watch next?"},
],
labels=["production"],
)
# Documented LangChain integration:
# https://langfuse.com/docs/prompt-management/features/message-placeholders
prompt = langfuse.get_prompt("movie-critic-chat")
langchain_prompt = ChatPromptTemplate.from_template(prompt.get_langchain_prompt())
# → logs WARNING: Placeholders ['chat_history'] have not been resolved.
# even though leaving it unresolved is EXACTLY what the docs tell you
# to do for LangChain integration.
Why this is a problem
- The docs at
/docs/prompt-management/features/message-placeholders
(LangChain Python tab) endorse this exact pattern —MessagesPlaceholder
objects in the output are the documented goal. - SDK can't distinguish "intentional unresolved (LangChain hand-off)" from
"misuse (forgot kwargs)" and warns in both cases. - No public API to silence: no
silent=/suppress_warnings=kwarg on
compile()orget_langchain_prompt(). logging.getLogger("langfuse").setLevel(...)is not a reliable
workaround — see langfuse/langfuse#4976 reporting setLevel doesn't
affect certain SDK-emitted warnings.- Forces every LangChain integrator to install a
logging.Filterthat
string-matches the warning message — brittle (breaks on copy edits)
and easy to over-silence.
Suggested fix
Add a silent=True (or suppress_unresolved_warning=True) kwarg to:
ChatPromptClient.compile(**kwargs, silent: bool = False)ChatPromptClient.get_langchain_prompt(**kwargs, silent: bool = False)
When silent=True, the
"Placeholders ['...'] have not been resolved" warning is skipped, but
other validation warnings (e.g. "Placeholder X must contain a list of
chat messages") still fire — those are genuine misuse signals.
Alternatively, get_langchain_prompt() could pass silent=True to its
internal compile() call by default, since by definition any unresolved
placeholder returned from this method is intended for LangChain.
Version info
- langfuse-python: 4.6.1 (also reproduces on 4.5.1 + main
HEAD) - langchain-core: 1.3.2
- Python: 3.11
Current workaround we use
contextlib.contextmanager that scopes a logging.Filter matching the
substring "have not been resolved" over the
chat_skeleton.get_langchain_prompt() call site. Fragile (depends on
warning string), but scoped narrowly so other langfuse warnings still
propagate.
Happy to send a PR if the maintainers agree with the kwarg shape.
- Dominant language
- Python
- Stars
- 468
- Forks
- 349
- Avg merge
- 15h 51m
- Merged PRs (30d)
- 24
Getting set up
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from langfuse/langfuse-python
-
mask is not applied to create_dataset_item or create_score(comment=)Possibly taken @hassiebp claimed this 3 days ago. Openbug compliance feat-data-masking sdk-python security
langfuse/langfuse-python#1896 · 1 comment · 1 assignee ·
Maintainers usually reply within 1 day
-
Scores bypass sample_rate since v4Possibly taken @hassiebp claimed this 8 days ago. Openfeat-scores sdk-python unconfirmed-bug
langfuse/langfuse-python#1890 · 1 assignee ·
Maintainers usually reply within 1 day
-
batch_evaluation fails on self-hosted v4 events_only deployments (uses unavailable v3 read endpoints)Possibly taken @hassiebp claimed this 21 days ago. Openbug feat-evals sdk-python
langfuse/langfuse-python#1861 · 2 comments · 1 assignee ·
Maintainers usually reply within 1 day
-
[HTTPXodus] Consider migrating from httpx to httpx2 (the actively maintained fork)Possibly taken @hassiebp claimed this 22 days ago. Openimprovement sdk-python
langfuse/langfuse-python#1856 · 1 assignee ·
Maintainers usually reply within 1 day
-
[HTTPXodus] Consider migrating from `httpx` to `httpx2` (the actively maintained fork)Possibly taken @hassiebp claimed this 22 days ago. Openimprovement sdk-python security
langfuse/langfuse-python#1855 · 1 assignee ·
Maintainers usually reply within 1 day
All issues in langfuse/langfuse-python
Similar issues
-
pydanty:is-working
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
pydantic/pydantic-ai#8843 ·
Maintainers usually reply within 1 day
-
breaking change enhancement server
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
Maintainers usually reply within 1 day
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
sktime/sktime#11310 · 1 comment ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
Maintainers usually reply within 1 day
-
needs-triage
Difficulty 2/5 1-3 hours Newbie friendliness 85/100
Maintainers usually reply within 1 day