{"record":{"id":"6910f8f5ac690fd1","repo":"PrefectHQ/fastmcp","slug":"authorization-failed-for-prompt-prompt-name-i","errorCode":null,"errorMessage":"Authorization failed for prompt '{prompt_name}': insufficient scope (required: {', '.join(missing)})","messagePattern":"Authorization failed for prompt '(.+?)': insufficient scope \\(required: (.+?)\\)","errorType":"exception","errorClass":"InsufficientScopeError","httpStatus":null,"severity":"error","filePath":"fastmcp_slim/fastmcp/server/middleware/authorization.py","lineNumber":443,"sourceCode":"        # 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                )\n            raise AuthorizationError(\n                f\"Authorization failed for prompt '{prompt_name}': insufficient permissions\"\n            )\n\n        return await call_next(context)\n","sourceCodeStart":425,"sourceCodeEnd":455,"githubUrl":"https://github.com/PrefectHQ/fastmcp/blob/1f021142978e0861cd910c8df4e8074bc7cf3978/fastmcp_slim/fastmcp/server/middleware/authorization.py#L425-L455","documentation":"Raised as InsufficientScopeError when the prompt was found and component-level auth ran scope checks, but the caller's access token is missing one or more required scopes. The error message lists the exact missing scopes after the middleware chains any shortfall through _chain_shortfall (which can add parent/scope-group requirements).","triggerScenarios":"on_get_prompt succeeded in fetching the prompt, run_auth_checks_with_shortfall returned authorized=False with a non-empty `missing` set — i.e. the prompt (or its auth config) declares required scopes the current token lacks.","commonSituations":"Token issued with narrower scopes than the prompt requires; provider scope mapping changed; prompt recently had required_scopes added; using a read-only API key for a prompt gated on admin scopes.","solutions":["Read the missing scopes from the error message and request a token containing them (re-run the OAuth flow with the expanded scope request).","If the scopes are wrong on the server side, remove or relax required scopes in the prompt's auth configuration.","Check _chain_shortfall expansion — the shortfall may include scopes inherited from scope groups/parents, so grant the base scope rather than each listed one."],"exampleFix":"// before\nawait client.get_prompt(\"admin_report\")  # token lacks admin:read\n\n// after: obtain a token with the required scope\nauth = OAuth(scopes=[\"admin:read\"])\nclient = Client(\"http://localhost:8000/mcp\", auth=auth)\nawait client.get_prompt(\"admin_report\")","handlingStrategy":"try-catch","validationCode":"// decode the token's scopes and compare to the prompt's requirements\nclaims = jwt.decode(token, options={\"verify_signature\": False})\nhave = set(claims.get(\"scope\", \"\").split())\nrequired = {\"admin:read\"}  # from prompt config\nif not required <= have:\n    raise PermissionError(f\"token missing scopes: {required - have}\")","typeGuard":null,"tryCatchPattern":"try:\n    result = await client.get_prompt(name)\nexcept Exception as e:\n    if \"insufficient scope\" in str(e):\n        missing = str(e).split(\"required: \")[-1]\n        token = await obtain_token(scopes=missing.split(\", \"))\n        result = await client.get_prompt(name)\n    else:\n        raise","preventionTips":["Request all scopes your app needs up front in the OAuth flow.","Track required_scopes for each gated prompt in app config.","Refresh tokens before expiry so scope downgrades don't surprise you.","Log missing scopes from the error to drive automated re-auth."],"tags":["authorization","oauth-scopes","prompts"],"backgroundTag":"insufficient-scope","analyzedSha":"1f021142978e0861cd910c8df4e8074bc7cf3978","analyzedAt":"2026-08-29T14:31:16.082Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}