Just had an app delete progress I had made after I changed the roles to allow another role to access the app. I've seen this bug in previous versions but I thought it was fixed already. Not sure if it matters but git sync is setup one way and was paused at the time. All changes were made through the PSU web interface.
Hello rmcavoy,
Thank you for reaching out to the Devolutions support team.
Could you explain in detail how to reproduce this issue?
I think it's worth the time to investigate further if the code is deleted ;)
Did you receive any error messages when changing the role?
Which role was impacted in this process?
Best regards,
Patrick Ouimet
Should be able to reproduce by changing the permitted roles for the app via the gui (Apps -> Apps Page and using the gear icon to change the app properties).
I already had the built in administrator role assigned to the app and once I had finished building the app to my liking I added a custom role to allow users to start using it. Once I did that (as described above) the app reloaded and changes I had made were no longer showing in the web code editor. When I checked the script file on the PSU host it still contained the missing code. I tried just restarting the app to reload the code but the only thing that seemed to work was restarting PSU entirely.
no error messages or any notification popped up when changing the role, everything seemed normal
Some additional info about our PSU instance:
I also notice that the app doesnt retain the custom role. I constantly have to reapply the role as it keeps reverting back to just administrators
Hello rmcavoy,
Thank you for the detailed reproduction steps and environment information.
Based on your observations (the script file on the host still containing the latest code, and the issue clearing only after restarting PSU), this looks like the web editor is temporarily loading an out-of-date version of the app after saving app properties (permitted roles). The fact that the custom role keeps reverting back to “Administrators” suggests the permission change may not be persisting reliably and/or is being overwritten during a reload/repository refresh.
To help us isolate the cause, could you please provide:
If possible, please also try reproducing once with Git sync fully disabled (not just paused) and let us know whether:
Best regards,
Patrick Ouimet
Git sync being paused just means I am making edits and have not committed them yet
I am not able to make changes to the git sync behavior as the server is in production
Today I got the same issue however it was not triggered by changing the roles, Im not sure what triggered it this time. I was working on a new app and after making some changes to a module and going back to the app it was reverted to the default script for a new app.
Here is what shows in the system log at the time:
2026-06-09 10:00:07.174 -04:00 [ERR][Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware] An unhandled exception has occurred while executing the request.
Grpc.Core.RpcException: Status(StatusCode="Unknown", Detail="Stream removed", DebugException="Grpc.Core.Internal.CoreErrorDetailException: {"created":"@1781013606.612000000","description":"Error received from peer ipv6:[::1]:57534","file":"..\..\..\src\core\lib\surface\call.cc","file_line":953,"grpc_message":"Stream removed","grpc_status":2}")
---> Grpc.Core.Internal.CoreErrorDetailException: {"created":"@1781013606.612000000","description":"Error received from peer ipv6:[::1]:57534","file":"..\..\..\src\core\lib\surface\call.cc","file_line":953,"grpc_message":"Stream removed","grpc_status":2}
--- End of inner exception stack trace ---
at ProtoBuf.Grpc.Internal.Reshape.UnaryTaskAsyncImpl[TRequest,TResponse](AsyncUnaryCall`1 call, MetadataContext metadata, CancellationToken cancellationToken)
at Universal.Server.Services.DashboardProxy.ExecuteEndpoint(DashboardExecuteEndpointRequest request) in D:\a\powershell-universal\powershell-universal\src\Universal.Server\Services\Dashboard\DashboardProxy.cs:line 670
at UniversalDashboard.Controllers.UDComponentController.RunScript(String endpointId, Dictionary`2 parameters, Boolean form) in D:\a\powershell-universal\powershell-universal\src\Universal.Server\Controllers\UDComponentController.cs:line 218
at UniversalDashboard.Controllers.UDComponentController.Element(String id) in D:\a\powershell-universal\powershell-universal\src\Universal.Server\Controllers\UDComponentController.cs:line 376
at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.TaskOfIActionResultExecutor.Execute(ActionContext actionContext, IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeActionMethodAsync>g__Logged|12_1(ControllerActionInvoker invoker)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeNextActionFilterAsync>g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeInnerFilterAsync>g__Awaited|13_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|25_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|20_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Logged|17_1(ResourceInvoker invoker)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Logged|17_1(ResourceInvoker invoker)
at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|7_0(Endpoint endpoint, Task requestTask, ILogger logger)
at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
at PowerShellUniversal.FeatureMiddleware.InvokeAsync(HttpContext context, RequestDelegate next) in D:\a\powershell-universal\powershell-universal\src\Universal.Server\Middleware\FeatureMiddleware.cs:line 42
at Microsoft.AspNetCore.Builder.UseMiddlewareExtensions.InterfaceMiddlewareBinder.<>c__DisplayClass2_0.<<CreateMiddleware>b__0>d.MoveNext()
--- End of stack trace from previous location ---
at PowerShellUniversal.DisallowedModeMiddleware.InvokeAsync(HttpContext context, RequestDelegate next) in D:\a\powershell-universal\powershell-universal\src\Universal.Server\Middleware\ModeMiddleware.cs:line 25
at Microsoft.AspNetCore.Builder.UseMiddlewareExtensions.InterfaceMiddlewareBinder.<>c__DisplayClass2_0.<<CreateMiddleware>b__0>d.MoveNext()
--- End of stack trace from previous location ---
at PowerShellUniversal.CspMiddleware.InvokeAsync(HttpContext context, RequestDelegate next) in D:\a\powershell-universal\powershell-universal\src\Universal.Server\Middleware\CspMiddleware.cs:line 28
at Microsoft.AspNetCore.Builder.UseMiddlewareExtensions.InterfaceMiddlewareBinder.<>c__DisplayClass2_0.<<CreateMiddleware>b__0>d.MoveNext()
--- End of stack trace from previous location ---
at Universal.Server.Middleware.RoutingMiddleware.Invoke(HttpContext httpContext, IPolicyEvaluator policyEvaluator) in D:\a\powershell-universal\powershell-universal\src\Universal.Server\Middleware\RoutingMiddleware.cs:line 185
at PowerShellUniversal.PSUMiddleware.InvokeAsync(HttpContext context, RequestDelegate next) in D:\a\powershell-universal\powershell-universal\src\Universal.Server\Middleware\PowerShellMiddleware.cs:line 15
at Microsoft.AspNetCore.Builder.UseMiddlewareExtensions.InterfaceMiddlewareBinder.<>c__DisplayClass2_0.<<CreateMiddleware>b__0>d.MoveNext()
--- End of stack trace from previous location ---
at Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext)
at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider)
at Universal.Server.Middleware.WindowsAuthMiddleware.InvokeAsync(HttpContext context, RequestDelegate next) in D:\a\powershell-universal\powershell-universal\src\Universal.Server\Middleware\WindowsAuthMiddleware.cs:line 58
at Microsoft.AspNetCore.Builder.UseMiddlewareExtensions.InterfaceMiddlewareBinder.<>c__DisplayClass2_0.<<CreateMiddleware>b__0>d.MoveNext()
--- End of stack trace from previous location ---
at Universal.Server.Middleware.SwaggerAuthenticationMiddleware.InvokeAsync(HttpContext context, RequestDelegate next) in D:\a\powershell-universal\powershell-universal\src\Universal.Server\Middleware\SwaggerAuthMiddleware.cs:line 51
at Microsoft.AspNetCore.Builder.UseMiddlewareExtensions.InterfaceMiddlewareBinder.<>c__DisplayClass2_0.<<CreateMiddleware>b__0>d.MoveNext()
--- End of stack trace from previous location ---
at StackExchange.Profiling.MiniProfilerMiddleware.Invoke(HttpContext context) in C:\projects\dotnet\src\MiniProfiler.AspNetCore\MiniProfilerMiddleware.cs:line 112
at AspNetCoreRateLimit.RateLimitMiddleware`1.Invoke(HttpContext context) in D:\a\powershell-universal\powershell-universal\src\AspNetCoreRateLimit\Middleware\RateLimitMiddleware.cs:line 109
at Microsoft.AspNetCore.Session.SessionMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Session.SessionMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddlewareImpl.<Invoke>g__Awaited|10_0(ExceptionHandlerMiddlewareImpl middleware, HttpContext context, Task task)
2026-06-09 10:00:07.216 -04:00 [ERR][Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware] An unhandled exception has occurred while executing the request.
Grpc.Core.RpcException: Status(StatusCode="Unknown", Detail="Stream removed", DebugException="Grpc.Core.Internal.CoreErrorDetailException: {"created":"@1781013606.612000000","description":"Error received from peer ipv6:[::1]:57534","file":"..\..\..\src\core\lib\surface\call.cc","file_line":953,"grpc_message":"Stream removed","grpc_status":2}")
---> Grpc.Core.Internal.CoreErrorDetailException: {"created":"@1781013606.612000000","description":"Error received from peer ipv6:[::1]:57534","file":"..\..\..\src\core\lib\surface\call.cc","file_line":953,"grpc_message":"Stream removed","grpc_status":2}
--- End of inner exception stack trace ---
at ProtoBuf.Grpc.Internal.Reshape.UnaryTaskAsyncImpl[TRequest,TResponse](AsyncUnaryCall`1 call, MetadataContext metadata, CancellationToken cancellationToken)
at Universal.Server.Services.DashboardProxy.ExecuteEndpoint(DashboardExecuteEndpointRequest request) in D:\a\powershell-universal\powershell-universal\src\Universal.Server\Services\Dashboard\DashboardProxy.cs:line 670
at UniversalDashboard.Controllers.UDComponentController.RunScript(String endpointId, Dictionary`2 parameters, Boolean form) in D:\a\powershell-universal\powershell-universal\src\Universal.Server\Controllers\UDComponentController.cs:line 218
at UniversalDashboard.Controllers.UDComponentController.Element(String id) in D:\a\powershell-universal\powershell-universal\src\Universal.Server\Controllers\UDComponentController.cs:line 376
at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.TaskOfIActionResultExecutor.Execute(ActionContext actionContext, IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeActionMethodAsync>g__Logged|12_1(ControllerActionInvoker invoker)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeNextActionFilterAsync>g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeInnerFilterAsync>g__Awaited|13_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|25_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|20_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Logged|17_1(ResourceInvoker invoker)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Logged|17_1(ResourceInvoker invoker)
at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|7_0(Endpoint endpoint, Task requestTask, ILogger logger)
at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
at PowerShellUniversal.FeatureMiddleware.InvokeAsync(HttpContext context, RequestDelegate next) in D:\a\powershell-universal\powershell-universal\src\Universal.Server\Middleware\FeatureMiddleware.cs:line 42
at Microsoft.AspNetCore.Builder.UseMiddlewareExtensions.InterfaceMiddlewareBinder.<>c__DisplayClass2_0.<<CreateMiddleware>b__0>d.MoveNext()
--- End of stack trace from previous location ---
at PowerShellUniversal.DisallowedModeMiddleware.InvokeAsync(HttpContext context, RequestDelegate next) in D:\a\powershell-universal\powershell-universal\src\Universal.Server\Middleware\ModeMiddleware.cs:line 25
at Microsoft.AspNetCore.Builder.UseMiddlewareExtensions.InterfaceMiddlewareBinder.<>c__DisplayClass2_0.<<CreateMiddleware>b__0>d.MoveNext()
--- End of stack trace from previous location ---
at PowerShellUniversal.CspMiddleware.InvokeAsync(HttpContext context, RequestDelegate next) in D:\a\powershell-universal\powershell-universal\src\Universal.Server\Middleware\CspMiddleware.cs:line 28
at Microsoft.AspNetCore.Builder.UseMiddlewareExtensions.InterfaceMiddlewareBinder.<>c__DisplayClass2_0.<<CreateMiddleware>b__0>d.MoveNext()
--- End of stack trace from previous location ---
at Universal.Server.Middleware.RoutingMiddleware.Invoke(HttpContext httpContext, IPolicyEvaluator policyEvaluator) in D:\a\powershell-universal\powershell-universal\src\Universal.Server\Middleware\RoutingMiddleware.cs:line 185
at PowerShellUniversal.PSUMiddleware.InvokeAsync(HttpContext context, RequestDelegate next) in D:\a\powershell-universal\powershell-universal\src\Universal.Server\Middleware\PowerShellMiddleware.cs:line 15
at Microsoft.AspNetCore.Builder.UseMiddlewareExtensions.InterfaceMiddlewareBinder.<>c__DisplayClass2_0.<<CreateMiddleware>b__0>d.MoveNext()
--- End of stack trace from previous location ---
at Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext)
at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider)
at Universal.Server.Middleware.WindowsAuthMiddleware.InvokeAsync(HttpContext context, RequestDelegate next) in D:\a\powershell-universal\powershell-universal\src\Universal.Server\Middleware\WindowsAuthMiddleware.cs:line 58
at Microsoft.AspNetCore.Builder.UseMiddlewareExtensions.InterfaceMiddlewareBinder.<>c__DisplayClass2_0.<<CreateMiddleware>b__0>d.MoveNext()
--- End of stack trace from previous location ---
at Universal.Server.Middleware.SwaggerAuthenticationMiddleware.InvokeAsync(HttpContext context, RequestDelegate next) in D:\a\powershell-universal\powershell-universal\src\Universal.Server\Middleware\SwaggerAuthMiddleware.cs:line 51
at Microsoft.AspNetCore.Builder.UseMiddlewareExtensions.InterfaceMiddlewareBinder.<>c__DisplayClass2_0.<<CreateMiddleware>b__0>d.MoveNext()
--- End of stack trace from previous location ---
at StackExchange.Profiling.MiniProfilerMiddleware.Invoke(HttpContext context) in C:\projects\dotnet\src\MiniProfiler.AspNetCore\MiniProfilerMiddleware.cs:line 112
at AspNetCoreRateLimit.RateLimitMiddleware`1.Invoke(HttpContext context) in D:\a\powershell-universal\powershell-universal\src\AspNetCoreRateLimit\Middleware\RateLimitMiddleware.cs:line 109
at Microsoft.AspNetCore.Session.SessionMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Session.SessionMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddlewareImpl.<Invoke>g__Awaited|10_0(ExceptionHandlerMiddlewareImpl middleware, HttpContext context, Task task)
f5161dbf-a091-4970-8364-f3aeb0395c67.png
Hello,
Thank you for the additional details, the screenshot, and the system log excerpt.
This is very helpful.
Based on everything gathered so far, I do not believe your code is actually being deleted. The key indicators are that the script file on the PSU host still contained the latest code, the web editor only showed the older/default version, and a full PSU restart was the only thing that reliably restored the correct view. That pattern points to the web editor temporarily loading an out-of-date, in-memory version of the app after a reload, rather than data being lost on disk.
A few points that line up with what you are seeing:
Suggested workaround:
Until this is fully addressed, the following sequence should help you avoid losing in-progress code and prevent the role change from reverting:
The key principle is to separate code changes from property/role changes, and to let your code reach the Git repository before any reload is triggered, so a reload re-reads your latest code rather than an out-of-date in-memory version.
To move this forward to a formal investigation, the remaining item that would help most is the broader system log covering a full reproduction (from the moment of the change through the app reload), in addition to the "Stream removed" excerpt you already shared.
For reference on the Git sync behaviour and how one-way mode is intended to work: https://docs.powershelluniversal.com/config/git
Best regards,
Patrick Ouimet