Primary_action not passing arguments correctly to whitelisted method inside frappe.msgprint()

Heya :wave:,

I’m having an issue with primary_action in frappe.msgprint() not properly passing arguments to a whitelisted method.

The Issue

When using primary_action to call frappe.core.doctype.user.user.reset_password, I get:

TypeError: reset_password() missing 1 required positional argument: 'user'

Code

Important context note: this code is part of a server script.

frappe.msgprint(
    msg="Email already exists. Click button to receive password reset email.",
    title="Existing User",
    indicator="orange",
    primary_action={
        'label': 'Send Reset Email',
        'server_action': 'frappe.core.doctype.user.user.reset_password',
        'args': {'user': doc.email},
    },
    raise_exception=True
)

What I’ve Verified

  • Network payload shows correct data: {"user":"test@example.com"}
  • Method signature: def reset_password(user: str) -> str:
  • Method is whitelisted: @frappe.whitelist(allow_guest=True, methods=["POST"])

Attempted Solutions

Tried different argument formats:

  • 'args': {'user': doc.email} :x:
  • 'args': doc.email :x:
  • 'user': doc.email :x:

Has anyone encountered this issue with primary_action argument passing form a frappe.msgprint() call? Is there a known workaround or correct syntax for passing arguments to whitelisted methods via primary_action?

Any insights would be greatly appreciated!
Cheers,
Antoine.

1 Like

Hello,

What is your version of apps?

I have copied your code and tested it is working.

Reset password request for user: testpassword@example.com
@frappe.whitelist(allow_guest=True, methods=["POST"])
@rate_limit(limit=get_password_reset_limit, seconds=60 * 60)
def reset_password(user: str) -> str:
	print(f"Reset password request for user: {user}")
	
    ...

Hey @Abdeali,

Thank you for your reply.

I am seeing this error on a site that runs Frappe Framework: v15.69.0

Here is an example where I’m running the code snippet straight into the system console

|

You’re able to run without issues? Including pressing the button to trigger the primary action?

Antoine.

Hey,

You are right running this code in system console is not working.

@frappe.whitelist(allow_guest=True, methods=["POST"])
@rate_limit(limit=get_password_reset_limit, seconds=60 * 60)
def reset_password( *args, **kwargs) -> str:
	print("reset_password", args, kwargs)
	...

result is:

reset_password () {'args': '{"user":"test@example.com"}', 'cmd': 'frappe.core.doctype.user.user.reset_password'}

Maybe frappe bug.

If you have custom app. Then why don’t you add this to your custom app.

Hey @Abdeali,

That is a good idea but I found a workaround.

Instead of sending a reset password email when the user clicks on the button I am redirecting them directly to the reset page like so:

    reset_link = frappe.utils.get_url() + "/login#forgot"
    frappe.msgprint(
        msg=f"""This email already belongs to a user .<br><br>
        <a href='{reset_link}' target='_blank' class='btn btn-primary btn-sm'>
            Reset my password
        </a><br><br>
        <small>Or copy this link: <code>{reset_link}</code></small>""",
        title="Existing User",
        indicator="orange",
        raise_exception=True,
    )

Thanks for looking into this and I agree that it looks like a bug!

Antoine.

2 Likes