anchor.diff:          _ ->
               {TargetRootName, StartFileCtx}
       end,
  -    % fixme fail if there is a recall in ancestors
  +    {StartFileDoc, StartFileCtx2} = file_ctx:get_file_doc(StartFileCtx1),
       {ok, SpaceId} = archive:get_space_id(ArchiveDoc),
  -    {IsDir, StartFileCtx2} = file_ctx:is_dir(StartFileCtx1),
  +    {IsDir, StartFileCtx3} = file_ctx:is_dir(StartFileCtx2),
  +    case archive_recall_cache:get(SpaceId, StartFileDoc) of
  +        {ok, {ongoing, _}} -> 
  +            ?ERROR_POSIX(?EBUSY);
  +        _ ->
  +            case create_root_file(IsDir, user_ctx:get_session_id(UserCtx), TargetParentGuid, FinalName) of
  +                {ok, RootFileGuid} ->
  +                    {RootPath, _} = file_ctx:get_canonical_path(file_ctx:new_by_guid(RootFileGuid)),
  +                    [_Sep, _SpaceId | RootPathTokens] = filename:split(RootPath),
  +                    TraverseInfo = #{
  +                        archive_doc => ArchiveDoc,
  +                        current_parent => TargetParentGuid,
  +                        root_path_tokens => RootPathTokens,
  +                        root_file_name => FinalName
  +                    },
  +                    setup_recall_traverse(
  +                        SpaceId, ArchiveDoc, RootFileGuid, TraverseInfo, StartFileCtx3, UserCtx),
  +                    {ok, RootFileGuid};
  +                {error, eexist} ->
  +                    ?ERROR_ALREADY_EXISTS;
  +                {error, Reason} ->
  +                    ?ERROR_POSIX(Reason)
  +            end
       
  -    case create_root_file(IsDir, user_ctx:get_session_id(UserCtx), TargetParentGuid, FinalName) of
  -        {ok, Guid} ->
  -            TaskId = file_id:guid_to_uuid(Guid),
  -            {RootPath, _} = file_ctx:get_canonical_path(file_ctx:new_by_guid(Guid)),
  -            [_Sep, _SpaceId | RootPathTokens] = filename:split(RootPath),
  -            case tree_traverse_session:setup_for_task(UserCtx, TaskId) of
  -                ok ->
  -                    {ok, ArchiveId} = archive:get_id(ArchiveDoc),
  -                    AdditionalData = #{
  -                        <<"spaceId">> => SpaceId
  -                    },
  -                    UserId = user_ctx:get_user_id(UserCtx),
  -                    Options = #{
  -                        task_id => TaskId,
  -                        children_master_jobs_mode => async,
  -                        follow_symlinks => external,
  -                        traverse_info => #{
  -                            archive_doc => ArchiveDoc,
  -                            current_parent => TargetParentGuid,
  -                            root_path_tokens => RootPathTokens,
  -                            root_file_name => FinalName
  -                        },
  -                        additional_data => AdditionalData
  -                    },
  -                    ok = archive_recall:create(TaskId, ArchiveDoc),
  -                    {ok, TaskId} = tree_traverse:run(?POOL_NAME, StartFileCtx2, UserId, Options),
  -                    ok = archive:report_recall_scheduled(ArchiveId, TaskId),
  -                    {ok, Guid};
  -                {error, _} = Error ->
  -                    Error
  -            end;
  -        {error, eexist} ->
  -            ?ERROR_ALREADY_EXISTS;
  -        Error ->
  -            Error
       end.
   
   
  
positive.code:     end.
  
  
  -spec recall_symlink(file_ctx:ctx(), file_id:file_guid(), [file_meta:name()], file_meta:name(), 
      archive:doc(), user_ctx:ctx()) -> {ok, file_ctx:ctx()}.
  recall_symlink(FileCtx, TargetParentGuid, RootPathTokens, FileName, ArchiveDoc, UserCtx) ->
  
negative.code:     {ok, file_ctx:new_by_guid(Guid)}.
  
  
  %% @private
  -spec report_error(id(), file_id:file_guid(), archive:doc(), term(), list()) -> ok.
  report_error(TaskId, FileGuid, ArchiveDoc, Reason, Stacktrace) ->
      {ok, ArchiveId} = archive:get_id(ArchiveDoc),
  