Is there an API available for moving folders?

I’m using Docspace v.3.1.1 with Docs v.9.0.3.29 (Community version), installed by Ubuntu 22.04.
Is there an API available for moving folders? When I attempt to use the code provided at Move or copy to a folder | ONLYOFFICE to batch move some folders and files from a room using folderIds and fileIds, an error occurs.

Move failed. Status code: 500, Message: {"error":{"message":"Could not resolve current tenant :-(.","type":"System.Exception","stack":"   at ASC.Files.Core.Data.FolderDao.GetFoldersQueryWithFilters(Int32 parentId, OrderBy orderBy, FilterType filterType, Boolean subjectGroup, Guid subjectId, String searchText, Boolean withSubfolders, Boolean excludeSubject, Int32 roomId, FilesDbContext filesDbContext) in /home/jenkins/workspace/appserver.deb/install/deb/debian/build/server/products/ASC.Files/Core/Core/Dao/TeamlabDao/FolderDao.cs:line 1815\n   at ASC.Files.Core.Data.FolderDao.GetFoldersAsync(Int32 parentId, OrderBy orderBy, FilterType filterType, Boolean subjectGroup, Guid subjectID, String searchText, Boolean withSubfolders, Boolean excludeSubject, Int32 offset, Int32 count, Int32 roomId, Boolean containingMyFiles, FolderType parentType, Boolean containingForms)+MoveNext() in /home/jenkins/workspace/appserver.deb/install/deb/debian/build/server/products/ASC.Files/Core/Core/Dao/TeamlabDao/FolderDao.cs:line 273\n   at ASC.Files.Core.Data.FolderDao.GetFoldersAsync(Int32 parentId, OrderBy orderBy, FilterType filterType, Boolean subjectGroup, Guid subjectID, String searchText, Boolean withSubfolders, Boolean excludeSubject, Int32 offset, Int32 count, Int32 roomId, Boolean containingMyFiles, FolderType parentType, Boolean containingForms)+System.Threading.Tasks.Sources.IValueTaskSource<System.Boolean>.GetResult()\n   at System.Linq.AsyncEnumerable.SelectEnumerableAsyncIterator`2.MoveNextCore() in /_/Ix.NET/Source/System.Linq.Async/System/Linq/Operators/Select.cs:line 221\n   at System.Linq.AsyncIteratorBase`1.MoveNextAsync() in /_/Ix.NET/Source/System.Linq.Async/System/Linq/AsyncIterator.cs:line 70\n   at System.Linq.AsyncIteratorBase`1.MoveNextAsync() in /_/Ix.NET/Source/System.Linq.Async/System/Linq/AsyncIterator.cs:line 75\n   at System.Linq.AsyncEnumerable.<ToListAsync>g__Core|424_0[TSource](IAsyncEnumerable`1 source, CancellationToken cancellationToken) in /_/Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToList.cs:line 36\n   at System.Linq.AsyncEnumerable.<ToListAsync>g__Core|424_0[TSource](IAsyncEnumerable`1 source, CancellationToken cancellationToken) in /_/Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToList.cs:line 36\n   at ASC.Web.Files.Services.WCFService.FileOperations.FileMoveCopyOperationsManager.<Publish>g__GetContent|3_0[T1](List`1 folderForContentIds, List`1 fileForContentIds) in /home/jenkins/workspace/appserver.deb/install/deb/debian/build/server/products/ASC.Files/Core/Services/WCFService/FileOperations/FileOperationsManager.cs:line 421\n   at ASC.Web.Files.Services.WCFService.FileOperations.FileMoveCopyOperationsManager.Publish(IEnumerable`1 folderIds, IEnumerable`1 fileIds, JsonElement destFolderId, Boolean copy, FileConflictResolveType resolveType, Boolean holdResult, Boolean toFillOut, Boolean content) in /home/jenkins/workspace/appserver.deb/install/deb/debian/build/server/products/ASC.Files/Core/Services/WCFService/FileOperations/FileOperationsManager.cs:line 389\n   at ASC.Files.Api.OperationController.MoveBatchItems(BatchRequestDto inDto)+MoveNext()\n   at ASC.Files.Api.OperationController.MoveBatchItems(BatchRequestDto inDto)+System.Threading.Tasks.Sources.IValueTaskSource<System.Boolean>.GetResult()\n   at System.Text.Json.Serialization.Converters.IAsyncEnumerableOfTConverter`2.OnWriteResume(Utf8JsonWriter writer, TAsyncEnumerable value, JsonSerializerOptions options, WriteStack& state)\n   at System.Text.Json.Serialization.JsonCollectionConverter`2.OnTryWrite(Utf8JsonWriter writer, TCollection value, JsonSerializerOptions options, WriteStack& state)\n   at System.Text.Json.Serialization.JsonConverter`1.TryWrite(Utf8JsonWriter writer, T& value, JsonSerializerOptions options, WriteStack& state)\n   at System.Text.Json.Serialization.JsonConverter`1.TryWriteAsObject(Utf8JsonWriter writer, Object value, JsonSerializerOptions options, WriteStack& state)\n   at System.Text.Json.Serialization.JsonConverter`1.TryWrite(Utf8JsonWriter writer, T& value, JsonSerializerOptions options, WriteStack& state)\n   at System.Text.Json.Serialization.Metadata.JsonPropertyInfo`1.GetMemberAndWriteJson(Object obj, WriteStack& state, Utf8JsonWriter writer)\n   at System.Text.Json.Serialization.Converters.ObjectDefaultConverter`1.OnTryWrite(Utf8JsonWriter writer, T value, JsonSerializerOptions options, WriteStack& state)\n   at System.Text.Json.Serialization.JsonConverter`1.TryWrite(Utf8JsonWriter writer, T& value, JsonSerializerOptions options, WriteStack& state)\n   at System.Text.Json.Serialization.JsonConverter`1.WriteCore(Utf8JsonWriter writer, T& value, JsonSerializerOptions options, WriteStack& state)\n   at System.Text.Json.Serialization.Metadata.JsonTypeInfo`1.SerializeAsync(PipeWriter pipeWriter, T rootValue, Int32 flushThreshold, CancellationToken cancellationToken, Object rootValueBoxed)\n   at System.Text.Json.Serialization.Metadata.JsonTypeInfo`1.SerializeAsync(PipeWriter pipeWriter, T rootValue, Int32 flushThreshold, CancellationToken cancellationToken, Object rootValueBoxed)\n   at System.Text.Json.Serialization.Metadata.JsonTypeInfo`1.SerializeAsync(PipeWriter pipeWriter, T rootValue, Int32 flushThreshold, CancellationToken cancellationToken, Object rootValueBoxed)\n   at Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonOutputFormatter.WriteResponseBodyAsync(OutputFormatterWriteContext context, Encoding selectedEncoding)\n   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResultFilterAsync>g__Awaited|30_0[TFilter,TFilterAsync](ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)\n   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResultExecutedContextSealed context)\n   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.ResultNext[TFilter,TFilterAsync](State& next, Scope& scope, Object& state, Boolean& isCompleted)\n   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeResultFilters()\n--- End of stack trace from previous location ---\n   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|25_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)\n   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)\n   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)\n   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeFilterPipelineAsync()\n--- End of stack trace from previous location ---\n   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)\n   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)\n   at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider)\n   at ASC.Api.Core.Middleware.LoggerMiddleware.Invoke(HttpContext context, TenantManager tenantManager, CoreSettings coreSettings, ILogger`1 logger)\n   at ASC.Api.Core.Middleware.CultureMiddleware.Invoke(HttpContext context, UserManager userManager, TenantManager tenantManager, AuthContext authContext)\n   at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)\n   at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)\n   at ASC.Core.TenantMiddleware.Invoke(HttpContext context, TenantManager tenantManager)\n   at ASC.Core.SynchronizationContextMiddleware.Invoke(HttpContext context)\n   at ASC.Api.Core.BaseStartup.<>c__DisplayClass21_0.<<Configure>b__3>d.MoveNext()\n--- End of stack trace from previous location ---\n   at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddlewareImpl.<Invoke>g__Awaited|10_0(ExceptionHandlerMiddlewareImpl middleware, HttpContext context, Task task)","hresult":-2146233088},"status":1,"statusCode":500}

However, if I pass fileIds without folderIds, all files are moved successfully. Additionally, passing only folderIds (without fileIds) results in the same error. Does this mean that the folderIds parameter is invalid? Could someone please clarify this confusion for me? Am I forced to move folders only by moving each file within the folders individually?

Hi @yuting, :wave:

Thank you for the description!

The error message

“Could not resolve current tenant”

usually indicates that the system cannot determine the tenant (portal) context for the request. Since moving files works but folders fail, this may be related either to how the request is formed or to specific conditions for folder operations.

To better understand the issue, could you please уточнить следующие моменты:


API request details

  • Could you share a full example of your request (without sensitive data like tokens)?
  • Which endpoint URL are you using? (mb PM)

Authorization

  • How are you authenticating your requests?

    • JWT?
    • cookies?
  • Does the same token/session work correctly with other API methods (e.g., listing folders)?


Data being used

  • How do you obtain:

    • folderIds
    • destFolderId
  • Are all these entities located:

    • within the same room?
    • within the same tenant?

Scenario clarification

  • Are you trying to move folders:

    • within the same room?
    • or between different rooms?

Isolation checks

  • What happens if you:

    • move a single folder?
    • move a folder without files inside?
  • Does the issue occur with all folders or only specific ones?

  • Could it be related to permissions (on the folder or its contents)?


Version check

  • Have you tried reproducing this behavior on a newer version of DocSpace?

This information will help us determine whether this is a configuration issue or a potential bug.

Looking forward to your reply :handshake: