Skip to content

fix message errors - #757

Open
simonLeary42 wants to merge 12 commits into
mainfrom
fix-message-bug
Open

fix message errors#757
simonLeary42 wants to merge 12 commits into
mainfrom
fix-message-bug

Conversation

@simonLeary42

@simonLeary42 simonLeary42 commented Jul 16, 2026

Copy link
Copy Markdown
Member

here is the error log:

[Thu Jul 16 03:33:08.793314 2026] [php:notice] [pid 323021] [client REDACTED:53309] internal server error: {"message":"","error":{"class":"UnityWebPortal\\\\lib\\\\exceptions\\\\UnityHTTPDMessageNotFoundException","msg":"message(level='success' title='SSH Key Added' body='Fingerprint: /J1uR4'), not found. found messages: []","location":"/srv/www/unity-web-2026-7-15/resources/lib/UnityHTTPD.php:383","trace":["#0 /srv/www/unity-web-2026-7-15/resources/lib/UnityHTTPD.php(405): UnityWebPortal\\\\lib\\\\UnityHTTPD::getMessageIndex()","#1 /srv/www/unity-web-2026-7-15/webroot/panel/ajax/delete_message.php(12): UnityWebPortal\\\\lib\\\\UnityHTTPD::deleteMessage()","#2 {main}"]},"REMOTE_USER":"REDACTED","REMOTE_ADDR":"REDACTED","errorid":"6a5850f4c1aca"}
[Thu Jul 16 03:33:08.797515 2026] [php:notice] [pid 321075] [client REDACTED:57743] internal server error: {"message":"","error":{"class":"UnityWebPortal\\\\lib\\\\exceptions\\\\UnityHTTPDMessageNotFoundException","msg":"message(level='success' title='SSH Key Removed' body='ssh-ed2551...iTBc REDACTED'), not found. found messages: [[\\"An internal server error has occurred.\\",\\"For assistance, contact a Unity admin at hpc@umass.edu.\\\\nError ID: 6a5850f4c1aca\\",\\"error\\"]]","location":"/srv/www/unity-web-2026-7-15/resources/lib/UnityHTTPD.php:383","trace":["#0 /srv/www/unity-web-2026-7-15/resources/lib/UnityHTTPD.php(405): UnityWebPortal\\\\lib\\\\UnityHTTPD::getMessageIndex()","#1 /srv/www/unity-web-2026-7-15/webroot/panel/ajax/delete_message.php(12): UnityWebPortal\\\\lib\\\\UnityHTTPD::deleteMessage()","#2 {main}"]},"REMOTE_USER":"REDACTED","REMOTE_ADDR":"REDACTED","errorid":"6a5850f4c2b35"}
[Thu Jul 16 03:33:08.800773 2026] [php:notice] [pid 321353] [client REDACTED:54750] internal server error: {"message":"","error":{"class":"UnityWebPortal\\\\lib\\\\exceptions\\\\UnityHTTPDMessageNotFoundException","msg":"message(level='success' title='SSH Key Added' body='Fingerprint: hbKNhr'), not found. found messages: [[\\"An internal server error has occurred.\\",\\"For assistance, contact a Unity admin at hpc@umass.edu.\\\\nError ID: 6a5850f4c1aca\\",\\"error\\"],[\\"An internal server error has occurred.\\",\\"For assistance, contact a Unity admin at hpc@umass.edu.\\\\nError ID: 6a5850f4c2b35\\",\\"error\\"]]","location":"/srv/www/unity-web-2026-7-15/resources/lib/UnityHTTPD.php:383","trace":["#0 /srv/www/unity-web-2026-7-15/resources/lib/UnityHTTPD.php(405): UnityWebPortal\\\\lib\\\\UnityHTTPD::getMessageIndex()","#1 /srv/www/unity-web-2026-7-15/webroot/panel/ajax/delete_message.php(12): UnityWebPortal\\\\lib\\\\UnityHTTPD::deleteMessage()","#2 {main}"]},"REMOTE_USER":"REDACTED","REMOTE_ADDR":"REDACTED","errorid":"6a5850f4c37f2"}
[Thu Jul 16 03:33:08.849725 2026] [php:notice] [pid 321353] [client REDACTED:54750] bad request: {"message":"$_POST has no array key 'level'","trace":["#0 /srv/www/unity-web-2026-7-15/resources/lib/UnityHTTPD.php(81): UnityWebPortal\\\\lib\\\\UnityHTTPD::errorLog()","#1 /srv/www/unity-web-2026-7-15/resources/lib/UnityHTTPD.php(174): UnityWebPortal\\\\lib\\\\UnityHTTPD::gracefulDie()","#2 /srv/www/unity-web-2026-7-15/resources/lib/UnityHTTPD.php(245): UnityWebPortal\\\\lib\\\\UnityHTTPD::badRequest()","#3 /srv/www/unity-web-2026-7-15/webroot/panel/ajax/delete_message.php(8): UnityWebPortal\\\\lib\\\\UnityHTTPD::getPostData()","#4 {main}"],"REMOTE_USER":"REDACTED","REMOTE_ADDR":"REDACTED","errorid":"6a5850f4cf72c"}
[Thu Jul 16 03:33:08.889782 2026] [php:notice] [pid 321075] [client REDACTED:57743] bad request: {"message":"$_POST has no array key 'level'","trace":["#0 /srv/www/unity-web-2026-7-15/resources/lib/UnityHTTPD.php(81): UnityWebPortal\\\\lib\\\\UnityHTTPD::errorLog()","#1 /srv/www/unity-web-2026-7-15/resources/lib/UnityHTTPD.php(174): UnityWebPortal\\\\lib\\\\UnityHTTPD::gracefulDie()","#2 /srv/www/unity-web-2026-7-15/resources/lib/UnityHTTPD.php(245): UnityWebPortal\\\\lib\\\\UnityHTTPD::badRequest()","#3 /srv/www/unity-web-2026-7-15/webroot/panel/ajax/delete_message.php(8): UnityWebPortal\\\\lib\\\\UnityHTTPD::getPostData()","#4 {main}"],"REMOTE_USER":"REDACTED","REMOTE_ADDR":"REDACTED","errorid":"6a5850f4d93a4"}
[Thu Jul 16 03:33:08.921718 2026] [php:notice] [pid 323021] [client REDACTED:53309] bad request: {"message":"$_POST has no array key 'level'","trace":["#0 /srv/www/unity-web-2026-7-15/resources/lib/UnityHTTPD.php(81): UnityWebPortal\\\\lib\\\\UnityHTTPD::errorLog()","#1 /srv/www/unity-web-2026-7-15/resources/lib/UnityHTTPD.php(174): UnityWebPortal\\\\lib\\\\UnityHTTPD::gracefulDie()","#2 /srv/www/unity-web-2026-7-15/resources/lib/UnityHTTPD.php(245): UnityWebPortal\\\\lib\\\\UnityHTTPD::badRequest()","#3 /srv/www/unity-web-2026-7-15/webroot/panel/ajax/delete_message.php(8): UnityWebPortal\\\\lib\\\\UnityHTTPD::getPostData()","#4 {main}"],"REMOTE_USER":"REDACTED","REMOTE_ADDR":"REDACTED","errorid":"6a5850f4e1065"}

here are those same lines json prettified:

[
    {
        "message": "",
        "error": {
            "class": "UnityWebPortal\\\\lib\\\\exceptions\\\\UnityHTTPDMessageNotFoundException",
            "msg": "message(level='success' title='SSH Key Added' body='Fingerprint: /J1uR4'), not found. found messages: []",
            "location": "/srv/www/unity-web-2026-7-15/resources/lib/UnityHTTPD.php:383",
            "trace": [
                "#0 /srv/www/unity-web-2026-7-15/resources/lib/UnityHTTPD.php(405): UnityWebPortal\\\\lib\\\\UnityHTTPD::getMessageIndex()",
                "#1 /srv/www/unity-web-2026-7-15/webroot/panel/ajax/delete_message.php(12): UnityWebPortal\\\\lib\\\\UnityHTTPD::deleteMessage()",
                "#2 {main}"
            ]
        }
    },
    {
        "message": "",
        "error": {
            "class": "UnityWebPortal\\\\lib\\\\exceptions\\\\UnityHTTPDMessageNotFoundException",
            "msg": "message(level='success' title='SSH Key Removed' body='ssh-ed2551...iTBc REDACTED'), not found. found messages: [[\\"An internal server error has occurred.\\",\\"For assistance, contact a Unity admin at hpc@umass.edu.\\\\nError ID: 6a5850f4c1aca\\",\\"error\\"]]",
            "location": "/srv/www/unity-web-2026-7-15/resources/lib/UnityHTTPD.php:383",
            "trace": [
                "#0 /srv/www/unity-web-2026-7-15/resources/lib/UnityHTTPD.php(405): UnityWebPortal\\\\lib\\\\UnityHTTPD::getMessageIndex()",
                "#1 /srv/www/unity-web-2026-7-15/webroot/panel/ajax/delete_message.php(12): UnityWebPortal\\\\lib\\\\UnityHTTPD::deleteMessage()",
                "#2 {main}"
            ]
        }
    },
    {
        "message": "",
        "error": {
            "class": "UnityWebPortal\\\\lib\\\\exceptions\\\\UnityHTTPDMessageNotFoundException",
            "msg": "message(level='success' title='SSH Key Added' body='Fingerprint: hbKNhr'), not found. found messages: [[\\"An internal server error has occurred.\\",\\"For assistance, contact a Unity admin at hpc@umass.edu.\\\\nError ID: 6a5850f4c1aca\\",\\"error\\"],[\\"An internal server error has occurred.\\",\\"For assistance, contact a Unity admin at hpc@umass.edu.\\\\nError ID: 6a5850f4c2b35\\",\\"error\\"]]",
            "location": "/srv/www/unity-web-2026-7-15/resources/lib/UnityHTTPD.php:383",
            "trace": [
                "#0 /srv/www/unity-web-2026-7-15/resources/lib/UnityHTTPD.php(405): UnityWebPortal\\\\lib\\\\UnityHTTPD::getMessageIndex()",
                "#1 /srv/www/unity-web-2026-7-15/webroot/panel/ajax/delete_message.php(12): UnityWebPortal\\\\lib\\\\UnityHTTPD::deleteMessage()",
                "#2 {main}"
            ]
        }
    },
    {
        "message": "$_POST has no array key 'level'",
        "trace": [
            "#0 /srv/www/unity-web-2026-7-15/resources/lib/UnityHTTPD.php(81): UnityWebPortal\\\\lib\\\\UnityHTTPD::errorLog()",
            "#1 /srv/www/unity-web-2026-7-15/resources/lib/UnityHTTPD.php(174): UnityWebPortal\\\\lib\\\\UnityHTTPD::gracefulDie()",
            "#2 /srv/www/unity-web-2026-7-15/resources/lib/UnityHTTPD.php(245): UnityWebPortal\\\\lib\\\\UnityHTTPD::badRequest()",
            "#3 /srv/www/unity-web-2026-7-15/webroot/panel/ajax/delete_message.php(8): UnityWebPortal\\\\lib\\\\UnityHTTPD::getPostData()",
            "#4 {main}"
        ]
    },
    {
        "message": "$_POST has no array key 'level'",
        "trace": [
            "#0 /srv/www/unity-web-2026-7-15/resources/lib/UnityHTTPD.php(81): UnityWebPortal\\\\lib\\\\UnityHTTPD::errorLog()",
            "#1 /srv/www/unity-web-2026-7-15/resources/lib/UnityHTTPD.php(174): UnityWebPortal\\\\lib\\\\UnityHTTPD::gracefulDie()",
            "#2 /srv/www/unity-web-2026-7-15/resources/lib/UnityHTTPD.php(245): UnityWebPortal\\\\lib\\\\UnityHTTPD::badRequest()",
            "#3 /srv/www/unity-web-2026-7-15/webroot/panel/ajax/delete_message.php(8): UnityWebPortal\\\\lib\\\\UnityHTTPD::getPostData()",
            "#4 {main}"
        ]
    },
    {
        "message": "$_POST has no array key 'level'",
        "trace": [
            "#0 /srv/www/unity-web-2026-7-15/resources/lib/UnityHTTPD.php(81): UnityWebPortal\\\\lib\\\\UnityHTTPD::errorLog()",
            "#1 /srv/www/unity-web-2026-7-15/resources/lib/UnityHTTPD.php(174): UnityWebPortal\\\\lib\\\\UnityHTTPD::gracefulDie()",
            "#2 /srv/www/unity-web-2026-7-15/resources/lib/UnityHTTPD.php(245): UnityWebPortal\\\\lib\\\\UnityHTTPD::badRequest()",
            "#3 /srv/www/unity-web-2026-7-15/webroot/panel/ajax/delete_message.php(8): UnityWebPortal\\\\lib\\\\UnityHTTPD::getPostData()",
            "#4 {main}"
        ]
    }
]

there's a lot that went wrong here:

  • the user double-clicked the clear messages button (I think)
  • the clear messages button's JS handler looped over each message and clicked each X button, twice
  • the backend failed to find each message the second time
  • UnityHTTPD::gracefulDie() caught the error, saw that there was a POST going on, and sent a redirect (nevermind the fact that the request was not for a webpage but an ajax endpoint)
  • while following the redirect, the browser changed the original request method POST into GET
  • while trying to process the new request, the backend attempted to read the POST data and failed because a specific array key was missing (nevermind the fact that the request method was not POST at all)
  • the missing array key error does not expose the contents of the array for debugging

fixed:

  • the clear messages button no longer loops over the other buttons, instead it calls a new AJAX endpoint which is much simpler and is idempotent
  • UnityHTTPD::gracefulDie() shall not redirect on ajax pages
  • when trying to access POST data, the backend shall first assert that the request method is actually POST
  • getQueryParameter(), getPostData() now expose the contents of the array for debugging when an array key is not found

not fixed:

  • UnityHTTPD::gracefulDie() still changes request method from POST to GET
    • This prevents an infinite loop
    • I have created a new function redirectOverrideMethodGet() to make it explicit what is going on, and changed the underlying redirect() so that the default behavior is to preserve the request method
  • it is still possible to double click the X button on an individual message and get a new error message
    • I started on making delete_message.php / UnityHTTPD::deleteMessage() idempotent, but this feels wrong because it could mask legitimate errors
    • Maybe if deleted messages were preserved in the session state, we could tell the difference between a message that never existed and a message that has already been deleted
  • Unlike most of the HTML forms in the account portal, ajax POSTs do not include CSRF protection
    • This could potentially be fixed in the future if we can enable auth for these endpoints

also changed:

  • the X button for a message will wait to hide elements it until the ajax request comes back successful
    • if the request fails, there are two evils to choose from:
      • hide the message but have it reappear the next time you load a page (previous behavior)
      • don't hide the message (I choose this one)
  • moved the clear messages button's visibility logic from backend to frontend
    • before:
      • the backend would render the button only when there were 3 or more messages
      • the frontend would hide the button only when there were 0 messages remaining
    • after:
      • the backend always renders the button
      • the frontend always shows the button when there are >= 3 messages and always hides the button when there are < 3 messages

here is a demo where I have repurposed the delete key button to send some messages instead:

Screen.Recording.2026-07-16.at.1.35.18.PM.mov

@simonLeary42
simonLeary42 marked this pull request as ready for review July 16, 2026 16:11
@simonLeary42
simonLeary42 requested a review from Copilot July 16, 2026 16:11

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR addresses message-clearing and AJAX error handling issues in the account portal by making message clearing idempotent, preventing redirects during AJAX error handling, and making redirect semantics explicit with respect to HTTP method preservation.

Changes:

  • Adds a new idempotent AJAX endpoint for clearing all messages and updates the UI logic to use it instead of programmatically clicking each dismiss button.
  • Updates UnityHTTPD::redirect() to preserve the request method by default (307) and introduces redirectOverrideMethodGet() (303) for explicit POST→GET PRG redirects; updates call sites accordingly.
  • Adds request method assertions (assertRequestMethod) and enforces POST-only access for POST data reads and specific endpoints.

Reviewed changes

Copilot reviewed 14 out of 14 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
webroot/panel/pi.php Uses explicit POST→GET redirect helper after PI actions.
webroot/panel/new_account.php Uses explicit POST→GET redirect helper after registration.
webroot/panel/groups.php Uses explicit POST→GET redirect helper for group membership actions.
webroot/panel/disabled_account.php Uses explicit POST→GET redirect helper after re-enabling an account.
webroot/panel/ajax/clear_messages.php Adds new POST-only endpoint to clear session messages.
webroot/panel/account.php Uses explicit POST→GET redirect helper after account-setting actions.
webroot/lan/api/bump-last-login.php Replaces manual method check with assertRequestMethod("POST").
webroot/js/messages.js Updates message dismissal UX; adds new “clear all” AJAX flow and frontend visibility logic.
webroot/admin/user-mgmt.php Uses explicit POST→GET redirect helper after “view as user”.
webroot/admin/pi-mgmt.php Uses explicit POST→GET redirect helper after PI group disable attempt.
resources/templates/header.php Uses explicit POST→GET redirect helper for global PRG handling; avoids redirects for admin clearView flow.
resources/templates/header.html.twig Always renders the Clear All Messages button (initially hidden); relies on JS to show/hide.
resources/lib/UnityHTTPD.php Adds redirectOverrideMethodGet, changes redirect status codes (307/303), skips redirects for AJAX in gracefulDie, adds assertRequestMethod, and enforces POST method in getPostData.
deployment/config.base.ini Bumps upstream version to 1.7.5.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread webroot/js/messages.js
Comment thread webroot/js/messages.js
Comment thread webroot/panel/ajax/clear_messages.php
Comment thread resources/lib/UnityHTTPD.php Outdated
@simonLeary42
simonLeary42 requested a review from bryank-cs July 16, 2026 17:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants