deepset-ai/haystack · error · ValueError

Variable '{var_name}' from {prompt_source} is already define

Error message

Variable '{var_name}' from {prompt_source} is already defined in the state schema. Please rename the variable or remove it from the prompt to avoid conflicts.

What it means

After path-traversal checks, read_skill_file verifies the resolved target is an existing regular file. This FileNotFoundError is raised when the path resolves within the skill directory but points at a nonexistent file or a directory. The message includes the list of readable files so callers can retry with a valid path.

Source

Thrown at haystack/components/agents/agent.py:578

        all_variables: dict[str, list[str]] = {}
        for builder, label in [
            (self._system_chat_prompt_builder, "system_prompt"),
            (self._user_chat_prompt_builder, "user_prompt"),
        ]:
            if builder is not None:
                # set required_variables on the builder, filtered to its own variables
                if required_variables == "*":
                    builder.required_variables = "*"
                elif isinstance(self.required_variables, list):
                    builder.required_variables = [v for v in self.required_variables if v in builder.variables]

                for var_name in builder.variables:
                    all_variables.setdefault(var_name, []).append(label)

        for var_name, sources in all_variables.items():
            prompt_source = " and ".join(sources)
            if var_name in self.resolved_state_schema:
                raise ValueError(
                    f"Variable '{var_name}' from {prompt_source} is already defined in the state schema. "
                    "Please rename the variable or remove it from the prompt to avoid conflicts."
                )
            if var_name in self._run_method_params:
                raise ValueError(
                    f"Variable '{var_name}' from {prompt_source} conflicts with input names in the run method. "
                    "Please rename the variable or remove it from the prompt to avoid conflicts."
                )
            if required_variables == "*" or (isinstance(required_variables, list) and var_name in required_variables):
                component.set_input_type(self, name=var_name, type=Any)
            else:
                component.set_input_type(self, name=var_name, type=Any, default=None)

    def warm_up(self) -> None:
        """Warm up the tools, hooks, and the underlying chat generator."""
        warm_up_tools(tools=self.tools)
        warm_up_hooks(self.hooks)
        if hasattr(self.chat_generator, "warm_up"):

View on GitHub (pinned to e318778c9b)

Solutions

  1. Use one of the file paths listed in the error's 'Readable files' hint.
  2. Call the store's listing API (e.g. via load_skill/_list_skill_files) to enumerate actual files and correct the path.
  3. Fix filename casing/spelling to exactly match the file on disk.

Example fix

// before
store.read_skill_file("my-skill", "Readme.md")
// after
store.read_skill_file("my-skill", "README.md")
Defensive patterns

Strategy: validation

Validate before calling

def assert_file_in_skill(store, name: str, path: str) -> bool:
    readable = store._list_skill_files(name) if hasattr(store, "_list_skill_files") else []
    return path in readable

Try / catch

try:
    content = store.read_skill_file(name, path)
except FileNotFoundError as e:
    logger.warning("%s; falling back to skill main file", e)
    content = store.read_skill_file(name, "SKILL.md")

Prevention

When it happens

Trigger: store.read_skill_file('my-skill', 'README.md') when the skill only ships 'SKILL.md'; a misspelled filename; passing a directory path; case-mismatched filename on case-sensitive filesystems.

Common situations: Hardcoded asset names that differ across skill versions; agent guessing file names ('readme.md' vs 'README.md'); referencing files deleted from the skill package; Linux deployments where Windows-authored casing no longer matches.

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


AI-assisted analysis of deepset-ai/haystack@e318778c9b (2026-08-30). Data as JSON: /api/errors/ce978021285afc2a. Report an issue: GitHub.