Issue with custom component
Bug Description
I have created a custom component under just to test
from langflow import CustomComponent from langflow.inputs import HandleInput from langflow.io import Output from langflow.schema.message import Message import random
class RandomTextAppender(CustomComponent): display_name: str = "Random Text Appender" description: str = "Appends a random phrase to text or message from any upstream component." icon = "🧩" name = "RandomTextAppender"
inputs = [
HandleInput(
name="input_value",
display_name="Text or Message",
input_types=["Message", "str"],
required=True,
)
]
outputs = [
Output(
name="output_value",
display_name="Modified Message",
method="build_results",
)
]
async def build_results(self) -> Message:
input_value = await self.get_input_value("input_value")
base_text = input_value.text if isinstance(input_value, Message) else str(input_value)
suffix = random.choice([
" – and that's a fact!",
" – more to come soon.",
" – believe it or not.",
" – stay tuned!",
])
return Message(text=base_text + suffix)
When i am connecting it is giving error as
Error building Component Random Text Appender:
'RandomTextAppender' object has no attribute 'get_input_value'
Traceback (most recent call last):
File "/app/.venv/lib/python3.12/site-packages/langflow/graph/vertex/base.py", line 632, in _build_results
result = await initialize.loading.get_instance_results(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/app/.venv/lib/python3.12/site-packages/langflow/interface/initialize/loading.py", line 68, in get_instance_results
return await build_component(params=custom_params, custom_component=custom_component)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/app/.venv/lib/python3.12/site-packages/langflow/interface/initialize/loading.py", line 145, in build_component
build_results, artifacts = await custom_component.build_results()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "
why these error how to fix. I have build from source with docker
Reproduction
Expected behavior
Who can help?
No response
Operating System
docker
Langflow Version
latest main repo
Python Version
3.12
Screenshot
No response
Flow File
No response
The error occurs because the method get_input_value does not exist on Langflow's CustomComponent class. In Langflow, custom components do not use get_input_value to access their inputs. Instead, input values are automatically assigned as attributes to your component instance, using the input name you defined.
To fix your RandomTextAppender, you should access the input directly as self.input_value inside your build method (or build_results if that's your output method). Here’s how you can update your component:
from langflow import CustomComponent
from langflow.inputs import HandleInput
from langflow.io import Output
from langflow.schema.message import Message
import random
class RandomTextAppender(CustomComponent):
display_name: str = "Random Text Appender"
description: str = "Appends a random phrase to text or message from any upstream component."
icon = "🧩"
name = "RandomTextAppender"
inputs = [
HandleInput(
name="input_value",
display_name="Text or Message",
input_types=["Message", "str"],
required=True,
)
]
outputs = [
Output(
name="output_value",
display_name="Modified Message",
method="build_results",
)
]
async def build_results(self) -> Message:
input_value = self.input_value # <-- Access input directly
base_text = input_value.text if isinstance(input_value, Message) else str(input_value)
suffix = random.choice([
" – and that's a fact!",
" – more to come soon.",
" – believe it or not.",
" – stay tuned!",
])
return Message(text=base_text + suffix)
You do not need to implement or call get_input_value; just use self.input_value as shown above. This approach matches how Langflow assigns input values to component instances, as described in the custom component documentation.
If you encounter further issues, make sure your custom component is placed in the correct directory (such as /app/custom_components/helpers/) and that the LANGFLOW_COMPONENTS_PATH environment variable is set appropriately in your Docker setup. Also, ensure there are no name overlaps between your inputs and outputs, and that your output method returns the correct type (in this case, a Message object) [source].
Let me know if you need more help!
To reply, just mention my name @dosu.
How did I do? Good | Irrelevant | Incorrect | Verbose | Hallucination | Report 🐛 | Other
@dosu
again i am getting this error Error building Component Random Text Appender:
'RandomTextAppender' object has no attribute 'input_value'
Traceback (most recent call last):
File "/app/.venv/lib/python3.12/site-packages/langflow/graph/vertex/base.py", line 632, in _build_results
result = await initialize.loading.get_instance_results(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/app/.venv/lib/python3.12/site-packages/langflow/interface/initialize/loading.py", line 68, in get_instance_results
return await build_component(params=custom_params, custom_component=custom_component)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/app/.venv/lib/python3.12/site-packages/langflow/interface/initialize/loading.py", line 145, in build_component
build_results, artifacts = await custom_component.build_results()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "
The code i have used is
from langflow import CustomComponent from langflow.inputs import HandleInput from langflow.io import Output from langflow.schema.message import Message import random
class RandomTextAppender(CustomComponent): display_name: str = "Random Text Appender" description: str = "Appends a random phrase to text or message from any upstream component." icon = "🧩" name = "RandomTextAppender"
inputs = [
HandleInput(
name="input_value",
display_name="Text or Message",
input_types=["Message", "str"],
required=True,
)
]
outputs = [
Output(
name="output_value",
display_name="Modified Message",
method="build_results",
)
]
async def build_results(self) -> Message:
input_value = self.input_value # ✅ Direct assignment from Langflow
base_text = input_value.text if isinstance(input_value, Message) else str(input_value)
suffix = random.choice([
" – and that's a fact!",
" – more to come soon.",
" – believe it or not.",
" – stay tuned!",
])
return Message(text=base_text + suffix)
and this is the flow
please help i am struggling
Your code and approach are correct according to the Langflow documentation: inputs defined in the class-level inputs list should be accessible as self.input_value in your method. However, if you are still getting 'RandomTextAppender' object has no attribute 'input_value', this usually means the input is not being set on the instance—often due to a loading or wiring issue in the custom component setup.
Here’s how to resolve and debug this:
-
Access input using
get_input:
Langflow’s custom component base class provides aget_inputmethod that safely retrieves the input value from the internal dictionary. Replace your input access line with:input_value = self.get_input("input_value")This method will raise a clear error if the input is missing and is the recommended way to access inputs in situations where direct attribute access fails [source].
-
Directory structure and environment variable:
Make sure your custom component file is inside a category subfolder (e.g.,/app/custom_components/helpers/random_text_appender.py) and not directly in/app/custom_components. The environment variableLANGFLOW_COMPONENTS_PATHmust be set to/app/custom_componentsin your Docker setup. Langflow will not load components placed directly in the base directory—they must be in a subfolder, which determines their category in the UI [source]. -
Restart Langflow after changes:
After adjusting the directory structure or environment variable, restart your Langflow Docker container to ensure changes take effect [source]. -
Debug attributes:
To debug, you can temporarily add this to yourbuild_resultsmethod:print("Component attributes:", dir(self))This will show you what attributes are present on your component instance at runtime.
Example fix:
async def build_results(self) -> Message:
input_value = self.get_input("input_value")
base_text = input_value.text if isinstance(input_value, Message) else str(input_value)
suffix = random.choice([
" – and that's a fact!",
" – more to come soon.",
" – believe it or not.",
" – stay tuned!",
])
return Message(text=base_text + suffix)
If you follow these steps and still encounter issues, double-check for typos in the input name and ensure there are no name overlaps or reserved attribute names in your component [source].
Let me know if this resolves your issue or if you see a different error!
To reply, just mention my name @dosu.
How did I do? Good | Irrelevant | Incorrect | Verbose | Hallucination | Report 🐛 | Other
@dosu I am not sure why custom component is not working , am i not building it from source thats why or what . I want to give you my docker file and compose.yml . And let me know what change i should do so that things can work in canvas it can wire and also i want to make changes in frontend . The idea is to build from source and add my components custom to langflow in python
My docker file is as build_and_push_with_extras.Dockerfile
syntax=docker/dockerfile:1 ################################
BUILDER-BASE ################################ FROM ghcr.io/astral-sh/uv:python3.12-bookworm-slim AS builder
WORKDIR /app
ENV UV_COMPILE_BYTECODE=1 ENV UV_LINK_MODE=copy
Install system dependencies RUN apt-get update && apt-get upgrade -y && apt-get install --no-install-recommends -y build-essential git npm gcc && apt-get clean && rm -rf /var/lib/apt/lists/*
Install backend dependencies from lock files RUN --mount=type=cache,target=/root/.cache/uv --mount=type=bind,source=uv.lock,target=uv.lock --mount=type=bind,source=README.md,target=README.md --mount=type=bind,source=pyproject.toml,target=pyproject.toml --mount=type=bind,source=src/backend/base/README.md,target=src/backend/base/README.md --mount=type=bind,source=src/backend/base/uv.lock,target=src/backend/base/uv.lock --mount=type=bind,source=src/backend/base/pyproject.toml,target=src/backend/base/pyproject.toml uv sync --frozen --no-install-project --no-editable --extra deploy --extra couchbase --extra cassio --extra local --extra clickhouse-connect --extra nv-ingest --extra postgresql
Copy everything (source, UI, components) COPY ./src /app/src
COPY src/frontend /tmp/src/frontend WORKDIR /tmp/src/frontend
Build frontend RUN --mount=type=cache,target=/root/.npm npm ci && NODE_OPTIONS="--max-old-space-size=4096" npm run build && cp -r build /app/src/backend/langflow/frontend && rm -rf /tmp/src/frontend
Install backend from your current source WORKDIR /app
COPY ./pyproject.toml /app/pyproject.toml COPY ./uv.lock /app/uv.lock COPY ./README.md /app/README.md COPY ./custom_components /app/custom_components
RUN --mount=type=cache,target=/root/.cache/uv uv sync --frozen --no-editable --extra deploy --extra couchbase --extra cassio --extra local --extra clickhouse-connect --extra nv-ingest --extra postgresql
################################
RUNTIME ################################ FROM python:3.12.3-slim AS runtime
RUN apt-get update && apt-get upgrade -y && apt-get install -y curl git libpq5 gnupg && curl -fsSL https://deb.nodesource.com/setup_18.x | bash - && apt-get install -y nodejs && apt-get clean && rm -rf /var/lib/apt/lists/* && useradd user -u 1000 -g 0 --no-create-home --home-dir /app/data
COPY --from=builder --chown=1000 /app/.venv /app/.venv COPY --from=builder --chown=1000 /app/custom_components /app/custom_components
ENV LANGFLOW_COMPONENTS_PATH=/app/custom_components
ENV PATH="/app/.venv/bin:$PATH"
LABEL org.opencontainers.image.title=langflow LABEL org.opencontainers.image.authors=['Langflow'] LABEL org.opencontainers.image.licenses=MIT LABEL org.opencontainers.image.url=https://github.com/langflow-ai/langflow LABEL org.opencontainers.image.source=https://github.com/langflow-ai/langflow
USER user WORKDIR /app
ENV LANGFLOW_HOST=0.0.0.0 ENV LANGFLOW_PORT=7860
CMD ["langflow", "run"]
Also Attaching the docker compose yaml , which is in parent directory services: langflow-app: build: context: . dockerfile: docker/build_and_push_with_extras.Dockerfile image: langflow-app container_name: langflow-app ports:
- "7860:7860" environment:
- LANGFLOW_DATABASE_URL=postgresql://langflow:langflow@postgres:5432/langflow
- LANGFLOW_SUPERUSER=admin
- LANGFLOW_SUPERUSER_PASSWORD=adminpassword
- LANGFLOW_SECRET_KEY=23648756921
- LANGFLOW_AUTO_LOGIN=false
- LANGFLOW_HOST=0.0.0.0
- LANGFLOW_PORT=7860
- LANGFLOW_COMPONENTS_PATH=/app/custom_components volumes:
- ./data:/app/data
- ./custom_components:/app/custom_components depends_on:
- postgres
postgres: image: postgres:16 container_name: postgres environment:
- POSTGRES_DB=langflow
- POSTGRES_USER=langflow
- POSTGRES_PASSWORD=langflow volumes:
- ./pgdata:/var/lib/postgresql/data ports:
- "5432:5432"
Also sharing the custom component directory structure and Code
He is the directory structure
Image
#------------- also sharing the code i have written for custom compnent i just want to wire it on canvas and get output something like that
from langflow import CustomComponent from langflow.inputs import HandleInput from langflow.io import Output from langflow.schema.message import Message import random
class RandomTextAppender(CustomComponent): display_name: str = "Random Text Appender" description: str = "Appends a random phrase to text or message from any upstream component." icon = "🧩" name = "RandomTextAppender"
inputs = [ HandleInput( name="input_value", display_name="Text or Message", input_types=["Message", "str"], required=True, ) ]
outputs = [ Output( name="output_value", display_name="Modified Message", method="build_results", ) ]
async def build_results(self) -> Message: print("⚠️ DEBUG: Entering build_results") print("⚠️ DEBUG: Component attributes:", dir(self))
try:
input_value = self.get_input("input_value")
print("⚠️ DEBUG: input_value =", input_value)
except Exception as e:
print("❌ ERROR getting input_value:", str(e))
raise ValueError(f"[RandomTextAppender] Failed to get input: {e}")
# Convert to string if needed
base_text = input_value.text if isinstance(input_value, Message) else str(input_value)
# Add random suffix
suffix = random.choice([
" – and that's a fact!",
" – more to come soon.",
" – believe it or not.",
" – stay tuned!",
])
final_text = base_text + suffix
print("✅ DEBUG: Final message:", final_text)
return Message(text=final_text)
what do you suggest am i not building the docker of lanflow from source , if so give me the complete docker file and docker compose to solve this problem
@yashugupta786 Here is the code for your component adjusted to Langlow standards (I created the component compatible with 1.6 with lfx inpiort, if you need to use it in an earlier version, change lfx to langflow):
import json
import random
from typing import Optional
from lfx.custom.custom_component.component import Component
from lfx.io import HandleInput, Output
from lfx.schema.message import Message
class RandomTextAppender(Component):
display_name = "Random Text Appender"
description = "Extracts inner text from a Message payload (if present) and appends a random phrase."
icon = "🧩"
name = "RandomTextAppender"
inputs = [
HandleInput(
name="input_value",
display_name="Text or Message",
input_types=["Message", "str"],
required=True,
)
]
outputs = [
Output(display_name="Message Output", name="message_output", method="get_message_output")
]
def _extract_text_from_possible_json(self, s: str, max_depth: int = 3) -> str:
if not isinstance(s, str) or not s:
return "" if s is None else str(s)
text = s.strip()
start_idx = text.find("{")
if start_idx == -1:
return text
depth = 0
end_idx: Optional[int] = None
for i in range(start_idx, len(text)):
ch = text[i]
if ch == "{":
depth += 1
elif ch == "}":
depth -= 1
if depth == 0:
end_idx = i
break
if end_idx is None:
return text
json_sub = text[start_idx : end_idx + 1]
try:
parsed = json.loads(json_sub)
except Exception:
return text
nested = None
if isinstance(parsed, dict):
nested = parsed.get("text", None)
if nested is None:
nested = parsed.get("content", None)
if isinstance(nested, str):
nested_str = nested.strip()
if max_depth > 0 and (nested_str.startswith("{") or '"text"' in nested_str):
return self._extract_text_from_possible_json(nested_str, max_depth - 1)
return nested
elif nested is not None:
return str(nested)
return text
def get_message_output(self) -> Message:
input_value = getattr(self, "input_value", None)
if input_value is None:
return Message(text="No input provided")
if isinstance(input_value, Message):
candidate = getattr(input_value, "text", None) or getattr(input_value, "content", None) or ""
elif isinstance(input_value, str):
candidate = input_value
else:
candidate = str(input_value)
extracted = self._extract_text_from_possible_json(candidate)
base_text = extracted if extracted else candidate
suffix = random.choice(
[
" – and that's a fact!",
" – more to come soon.",
" – believe it or not.",
" – stay tuned!",
]
)
final_text = base_text + suffix
return Message(text=final_text)
If you need more examples, I have a repository with dozens of components: https://github.com/Empreiteiro/langflow-factory
You can also count on the GPT component maker: https://chatgpt.com/g/g-67ae2e4396a48191a0e292d370ddd3d0-component-maker-agent
And whenever needed, our custom components documentation: https://docs.langflow.org/components-custom-components