langfuse / langfuse/langfuse-python

Suppress "Placeholders have not been resolved" warning when MessagesPlaceholder use is intentional (LangChain integration)

Open
#1,667 1 comment 0 reactions 1 assignee View on GitHub

@hassiebp is already working on this.

Since May 22, 2026.

bug integration-langchain integrations sdk-python
Dominant language
Python
Stars
467
Forks
348
Avg merge
12h 16m
Merged PRs (30d)
27

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

  1. 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.
  2. SDK can't distinguish "intentional unresolved (LangChain hand-off)" from
    "misuse (forgot kwargs)" and warns in both cases.
  3. No public API to silence: no silent= / suppress_warnings= kwarg on
    compile() or get_langchain_prompt().
  4. logging.getLogger("langfuse").setLevel(...) is not a reliable
    workaround — see langfuse/langfuse#4976 reporting setLevel doesn't
    affect certain SDK-emitted warnings.
  5. Forces every LangChain integrator to install a logging.Filter that
    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.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.