Skip to content

Conversation

@mkitti
Copy link
Contributor

@mkitti mkitti commented Jan 5, 2026

Fix #283 so that error responses do not result in JSON parsing errors of
that error response being displayed.

Before:
Image

After:

image

Assisted by Gemini 3 Pro (Low) via Antigravity.

@krokicki
Copy link
Member

krokicki commented Jan 6, 2026

I think it's useful to do some defensive programming here, but we should also try to understand why this response is being generated, and change it so that it generates JSON.

The Starlette exception handlers should be doing this, and it seems that is not working somehow.

    @app.exception_handler(StarletteHTTPException)
    async def http_exception_handler(request, exc):
        return JSONResponse({"error":str(exc.detail)}, status_code=exc.status_code)


    @app.exception_handler(RequestValidationError)
    async def validation_exception_handler(request, exc):
        return JSONResponse({"error":str(exc)}, status_code=400)

-inherits from PermissionError
-created to distinguish this specific configuration error from other PermissionErrors
- not catching PermissionErrors was what was originally causing no JSON response to be returned from the server when setegid, setgroups, or seteuid failed. Even those these specific errors are not caught by the custom error class and handler, I left in the global PermissionError handler to catch other instances where a PermissionError might not be caught in a specific method
- catch PermissionErrors in EffectiveUserContext.__enter__() and raise the new custom error class instead
@allison-truhlar
Copy link
Collaborator

This frontend fix works for me as expected. I tested it with use_access_flags=true in the config.yaml. I also tested visiting files I didn't have permission to view when use_access_flags=false to ensure the permission error still showed up as expected.

I opened a PR against this branch to address Konrad's comment.

allison-truhlar and others added 3 commits January 6, 2026 13:49
The error message was replicated in three places. Doing this means we
can set it once but still override it if needed.
…ser-context-error

fix: server response for user context error
@neomorphic
Copy link
Member

I think it's useful to do some defensive programming here, but we should also try to understand why this response is being generated, and change it so that it generates JSON.

The Starlette exception handlers should be doing this, and it seems that is not working somehow.

In reference to the comment, it looks like these two handlers do not catch all exceptions and so would not trigger on all occasions. We could add a general handler like this:

@app.exception_handler(Exception)
async def general_exception_handler(request, exc):
    logger.exception(f"Unhandled exception: {exc}")
    return JSONResponse({"error": str(exc)}, status_code=500)

This should catch everything and return a JSON response. The question is do we want all our 500 errors to be JSON responses? I think it will be fine, since the current 500 error response is a plain text document with

 "Internal Server Error"

and the new error response would be

{"error":"[Errno 1] Operation not permitted"}

Neither are very helpful to the user, but the second one does show better error messages when displayed in the application.

Copy link
Member

@neomorphic neomorphic left a comment

Choose a reason for hiding this comment

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

The frontend changes look good. There are probably many more cases (~25) where the response.json() should be caught to prevent this issue elsewhere. It looks like there are a number of instances later on in frontend/src/queries/fileQueries.ts that simply return an empty object if the json() method fails.

const body = await response.json().catch(() => ({}));

@allison-truhlar
Copy link
Collaborator

The frontend changes look good. There are probably many more cases (~25) where the response.json() should be caught to prevent this issue elsewhere. It looks like there are a number of instances later on in frontend/src/queries/fileQueries.ts that simply return an empty object if the json() method fails.

const body = await response.json().catch(() => ({}));

@neomorphic With the PR off this branch that addressed your above comment completed and merged, is this PR okay to merge into main now?

@neomorphic
Copy link
Member

neomorphic commented Jan 9, 2026

@neomorphic With the PR off this branch that addressed your above comment completed and merged, is this PR okay to merge into main now?

@allison-truhlar, Yeah, it should be fine.

@allison-truhlar allison-truhlar merged commit 41e90e0 into main Jan 9, 2026
7 checks passed
@allison-truhlar allison-truhlar deleted the mkitti-handle-internal-server-errors-file-queries branch January 9, 2026 16:04
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.

fileglancer attempts to parse the returned response contents as JSON despite a response code of 500.

5 participants