{"record":{"id":"93c275d8a8707099","repo":"PrefectHQ/fastmcp","slug":"authorization-failed-for-prompt-prompt-name-n","errorCode":null,"errorMessage":"Authorization failed for prompt '{prompt_name}': not found or not authorized","messagePattern":"Authorization failed for prompt '(.+?)': not found or not authorized","errorType":"exception","errorClass":"AuthorizationError","httpStatus":null,"severity":"error","filePath":"fastmcp_slim/fastmcp/server/middleware/authorization.py","lineNumber":431,"sourceCode":"        prompt_name = context.message.name\n        fastmcp = context.fastmcp_context\n        if fastmcp is None:\n            logger.warning(\n                f\"AuthMiddleware: fastmcp_context is None for prompt '{prompt_name}'. \"\n                \"Denying access for security.\"\n            )\n            raise AuthorizationError(\n                f\"Authorization failed for prompt '{prompt_name}': missing context\"\n            )\n\n        # get_prompt returns None both when the prompt does not exist and when\n        # component-level auth denied access, so the two cases are\n        # indistinguishable here. Keep the message ambiguous to avoid\n        # disclosing existence of prompts the caller is not authorized to see.\n        version = _requested_version(context.message.meta)\n        prompt = await fastmcp.fastmcp.get_prompt(prompt_name, version=version)\n        if prompt is None:\n            raise AuthorizationError(\n                f\"Authorization failed for prompt '{prompt_name}': \"\n                \"not found or not authorized\"\n            )\n\n        # Global auth check\n        token = get_access_token()\n        ctx = AuthContext(token=token, component=prompt)\n        authorized, missing = await run_auth_checks_with_shortfall(self.auth, ctx)\n        if not authorized:\n            if missing:\n                missing = self._chain_shortfall(missing, ctx, fastmcp.fastmcp)\n                raise InsufficientScopeError(\n                    missing,\n                    message=(\n                        f\"Authorization failed for prompt '{prompt_name}': \"\n                        f\"insufficient scope (required: {', '.join(missing)})\"\n                    ),\n                )","sourceCodeStart":413,"sourceCodeEnd":449,"githubUrl":"https://github.com/PrefectHQ/fastmcp/blob/1f021142978e0861cd910c8df4e8074bc7cf3978/fastmcp_slim/fastmcp/server/middleware/authorization.py#L413-L449","documentation":"Raised by the authorization middleware's on_get_prompt when a requested prompt cannot be retrieved. Because component-level auth denial and non-existence are deliberately indistinguishable, the message is ambiguous to avoid disclosing the existence of prompts the caller is not authorized to see. It is an AuthorizationError, so the problem is access control, not prompt registration alone.","triggerScenarios":"Calling prompts/get for a prompt_name that (a) does not exist on the server, (b) exists but has component-level auth (e.g. an auth predicate or required scopes) denying the caller, or (c) is filtered out for this identity — all funnel into fastmcp.get_prompt() returning None.","commonSituations":"Typo in the prompt name; prompt registered under a different name or version than requested; an AuthProvider or per-component auth check denies the caller's token; token expired or lacks the roles the prompt's auth check requires.","solutions":["Verify the exact prompt name via prompts/list (as the same authenticated identity) — if it is absent from the list, fix the name or registration.","If the prompt exists but still fails, check the token: is it valid, expired, and does it satisfy the prompt's component-level auth/scope requirements?","Review the middleware's AuthProvider configuration and any auth predicates on the @mcp.prompt decorator to confirm the caller's identity is permitted.","If a specific version was requested via meta, confirm a prompt variant with that version exists."],"exampleFix":"// before: guessing a prompt name\nawait client.get_prompt(\"summarize_doc\")\n\n// after: confirm it exists and is callable first\nprompts = await client.list_prompts()\nassert any(p.name == \"summarize_doc\" for p in prompts)\nawait client.get_prompt(\"summarize_doc\")","handlingStrategy":"validation","validationCode":"prompts = await client.list_prompts()\nif not any(p.name == prompt_name for p in prompts):\n    raise LookupError(f\"prompt '{prompt_name}' not available to this identity\")","typeGuard":null,"tryCatchPattern":"try:\n    result = await client.get_prompt(name)\nexcept Exception as e:\n    if \"not found or not authorized\" in str(e):\n        # treat as missing OR forbidden: check list_prompts / credentials\n        ...\n    raise","preventionTips":["Discover prompt names via prompts/list instead of hardcoding them.","Keep prompt names and versions in a shared constant/module.","Verify the auth provider grants the intended identity access to each prompt.","When requesting a versioned prompt, confirm the variant exists."],"tags":["authorization","prompts","mcp"],"backgroundTag":"resource-not-found-or-forbidden","analyzedSha":"1f021142978e0861cd910c8df4e8074bc7cf3978","analyzedAt":"2026-08-29T14:31:16.082Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}