rohitg00/ai-engineering-from-scratch · error · ValueError

unknown prompt

Error message

unknown prompt

What it means

The name passed to prompts/get is a string but is not a key in the server's self.prompts registry. The simulator registers a fixed set of prompt templates at construction; anything else is unknown. Enumerate valid names first via prompts/list, whose response contains each prompt's exact name.

Source

Thrown at certifications/claude/lessons/11-mcp-server-design-and-integration/code/main.py:295

                    }
                ],
                ttlMs=30_000,
                cacheScope="private",
            ), []
        if method == "prompts/list":
            prompts = [
                {"name": name, "description": self.prompts[name]}
                for name in sorted(self.prompts)
            ]
            return self._complete(
                prompts=prompts, ttlMs=300_000, cacheScope="public"
            ), []
        if method == "prompts/get":
            name = params["name"]
            if not isinstance(name, str):
                raise ValueError("name must be a string")
            if name not in self.prompts:
                raise ValueError("unknown prompt")
            return self._complete(
                messages=[
                    {
                        "role": "user",
                        "content": {"type": "text", "text": self.prompts[name]},
                    }
                ]
            ), []
        raise LookupError(f"Method not found: {method}")

    def _call_tool(
        self, params: dict[str, Any], metadata: dict[str, Any]
    ) -> tuple[dict[str, Any], list[dict[str, Any]]]:
        name = params["name"]
        if not isinstance(name, str) or not name:
            raise ValueError("name must be a non-empty string")
        tool = self.tools.get(name)
        if tool is None:

View on GitHub (pinned to 39ea8a1c6d)

Solutions

  1. Call prompts/list and use a name from the response exactly as returned
  2. Copy the name character-for-character — no renaming, casing changes, or pluralization
  3. If a needed prompt is missing, register it server-side or update the client's expected catalog

Example fix

# before
server.exchange("prompts/get", {"name": "sumarize", "_meta": meta})
# after
listed = server.exchange("prompts/list", {"_meta": meta})[0]
name = listed["prompts"][0]["name"]
server.exchange("prompts/get", {"name": name, "_meta": meta})
Defensive patterns

Strategy: validation

Validate before calling

listed = server.exchange("prompts/list", {"_meta": meta})[0]
names = {p["name"] for p in listed["prompts"]}
if name not in names:
    raise LookupError(f"unknown prompt {name!r}; known: {sorted(names)}")

Type guard

def prompt_exists(server, name: str) -> bool:
    return name in getattr(server, "prompts", {})

Try / catch

try:
    server.exchange("prompts/get", params)
except ValueError as e:
    if str(e) == "unknown prompt":
        params["name"] = pick_from_prompts_list()  # reselect and retry once
    else:
        raise

Prevention

When it happens

Trigger: prompts/get with "summarize" when the registry only has "summarise" or "summary"; hardcoding a prompt name removed in a server update; querying prompts that exist on a different MCP server.

Common situations: Prompt catalogs renamed between versions; multi-server setups where a name is routed to the wrong server; docs referencing prompts this deployment does not install.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


AI-assisted analysis of rohitg00/ai-engineering-from-scratch@39ea8a1c6d (2026-08-26). Data as JSON: /api/errors/3568c2e302715a11. Report an issue: GitHub.