After mu deploy, a Lambda Function URL created with AuthType=NONE returns 403 Forbidden / x-amzn-ErrorType: AccessDeniedException for every request, even though the auth type is NONE and the resource policy looks correct.
Root cause: since October 2025, new Lambda Function URLs require both lambda:InvokeFunctionUrl and lambda:InvokeFunction in the resource-based policy. mu only adds lambda:InvokeFunctionUrl, so the policy is incomplete and AWS denies the request.
From the AWS docs:
Starting in October 2025, new function URLs will require both lambda:InvokeFunctionUrl and lambda:InvokeFunction permissions.
If a function's resource-based policy doesn't grant lambda:InvokeFunctionUrl and lambda:InvokeFunction permissions, users will get a 403 Forbidden error code when they try to invoke your function URL. This will occur even if the function URL uses the NONE auth type.
Docs: https://docs.aws.amazon.com/lambda/latest/dg/urls-auth.html
Where it happens in mu
mu/libs/lamb.py, function_url() creates the URL config with AuthType='NONE' and then calls add_permission for only lambda:InvokeFunctionUrl:
self.lc.add_permission(
FunctionName=func_arn,
StatementId='AllowPublicAccessFunctionUrl',
Action='lambda:InvokeFunctionUrl',
Principal='*',
FunctionUrlAuthType='NONE',
)
The second statement required by AWS (the lambda:InvokeFunction action, scoped to function-URL calls via lambda:InvokedViaFunctionUrl) is never added.
Reproduction
mu provision <env> + mu deploy --build <env> for a function with a public (NONE) Function URL.
curl https://<id>.lambda-url.<region>.on.aws/ → 403, body {"Message":"Forbidden. For troubleshooting Function URL authorization issues..."}.
aws lambda get-function-url-config shows AuthType: NONE; aws lambda get-policy shows only the lambda:InvokeFunctionUrl statement.
Workaround
Add the missing lambda:InvokeFunction statement manually after deploy (it persists across subsequent mu deploy runs; only needs re-adding if the function is deleted and recreated):
aws lambda add-permission \
--function-name <function-name> \
--statement-id FunctionURLInvokeAllowPublicAccess \
--action lambda:InvokeFunction \
--principal '*' \
--invoked-via-function-url
Suggested fix
In function_url(), when creating a NONE Function URL, add the second permission statement alongside the existing one (mirrors what the Lambda console / AWS SAM now generate automatically):
self.lc.add_permission(
FunctionName=func_arn,
StatementId='FunctionURLInvokeAllowPublicAccess',
Action='lambda:InvokeFunction',
Principal='*',
InvokedViaFunctionUrl=True,
)
(The same dual-permission requirement also applies to AuthType=AWS_IAM URLs.)
After
mu deploy, a Lambda Function URL created withAuthType=NONEreturns403 Forbidden/x-amzn-ErrorType: AccessDeniedExceptionfor every request, even though the auth type isNONEand the resource policy looks correct.Root cause: since October 2025, new Lambda Function URLs require both
lambda:InvokeFunctionUrlandlambda:InvokeFunctionin the resource-based policy.muonly addslambda:InvokeFunctionUrl, so the policy is incomplete and AWS denies the request.From the AWS docs:
Docs: https://docs.aws.amazon.com/lambda/latest/dg/urls-auth.html
Where it happens in mu
mu/libs/lamb.py,function_url()creates the URL config withAuthType='NONE'and then callsadd_permissionfor onlylambda:InvokeFunctionUrl:The second statement required by AWS (the
lambda:InvokeFunctionaction, scoped to function-URL calls vialambda:InvokedViaFunctionUrl) is never added.Reproduction
mu provision <env>+mu deploy --build <env>for a function with a public (NONE) Function URL.curl https://<id>.lambda-url.<region>.on.aws/→403, body{"Message":"Forbidden. For troubleshooting Function URL authorization issues..."}.aws lambda get-function-url-configshowsAuthType: NONE;aws lambda get-policyshows only thelambda:InvokeFunctionUrlstatement.Workaround
Add the missing
lambda:InvokeFunctionstatement manually after deploy (it persists across subsequentmu deployruns; only needs re-adding if the function is deleted and recreated):Suggested fix
In
function_url(), when creating aNONEFunction URL, add the second permission statement alongside the existing one (mirrors what the Lambda console / AWS SAM now generate automatically):(The same dual-permission requirement also applies to
AuthType=AWS_IAMURLs.)